<commit_before>use std::collections::HashMap;

use logic::{Logic,Expect};
use eval::Eval;
use var::{Var,Mut};
use parse::{Parser,Map,Def,IR};

/// Source block statement types
#[derive(Debug,PartialEq)]
pub enum Src {
    /// Standard logic, eg: has_sword_item i
    Logic(String, Logic),

    /// References logic in env and emits varkinds
    ///
    /// Logic must resolve to true
    /// eg: if item_logic give_quest
    /// Can optionally end execution and begin next node
    If(Expect, Vec<Var>, Option<Next>),

    /// Or must follow an previous If
    ///
    /// Or only fires when previous If logic fails
    Or(Vec<Var>,Option<Next>),

    /// Just emits variables
    Emit(Vec<Var>),

    /// A composite logic type to group logic statements together
    Composite(String,Expect,Vec<String>),

    /// Ends execution and begins next node
    Next(Next),

    /// Mutate type, var being mutated, argument vars
    Mut(Mut, String, Vec<Var>),

    /// Match-like behavior for Mutations
    ///
    /// Map format should have Logic-Tested for the key
    /// and Mutation Function Signature for the value
    When(WhenMap),
}

/// Internal type to hold a specialized When-Mutate Map
pub type WhenMap = HashMap<String,(Mut,String,Vec<Var>)>;

/// Next-node action types
#[derive(Debug,PartialEq,Clone)]
pub enum Next {
    /// Instantly advances
    Now(String),

    /// Restarts current node, optionally another node -- heads immediately to this node on next evaluation
    Restart(Option<String>),

    /// Heads back to previous node visited
    Back,

    /// Clears out Node stack, pushes current node for further evaluation
    Clear,

    /// Awaits for manual advancement, failure to advance continues current node
    Await(String),

    /// Select from a group, based on decision
    Select(Map),

    /// Exits evaluation completely
    Exit
}
impl Next {
    pub fn parse(exp: &mut Vec<IR>) -> Result<Next,&'static str> {
        let mut select_idx = None;
        for (i,n) in exp.iter().enumerate() {
            match n {
                &IR::Sym(ref s) => {
                    if s == &"next:select" {
                        select_idx = Some(i);
                        break
                    }
                },
                _ => {},
            }
        }

        // handle nested selects as a special case
        if let Some(idx) = select_idx {
            let map_ir = exp.remove(idx+1);
            let _ = exp.remove(idx); // next:select statement
            if let Ok(map) = Parser::parse_map(map_ir) {
                return Ok(Next::Select(map))
            }
            else { return Err("Cannot parse map") }
        }

        let next;
        if let Some(node) = exp.pop() {
            if let Some(tag) = exp.pop() {
                match tag {
                    IR::Sym(tag) => {
                        let mut next_tag = tag.split_terminator(':');
                        let is_next = next_tag.next() == Some("next");

                        if is_next {
                            let next_tag = next_tag.next();
                            match next_tag {
                                Some("now") => { next = Next::Now(node.into()) },
                                Some("await") => { next = Next::Await(node.into()) },
                                Some("restart") => { next = Next::Restart(Some(node.into())) },
                                _ => { return Err("Invalid Next Type Found") },
                            }
                        }
                        else if next_tag.next().is_some() {
                            return Err("Unknown Tag encountered")
                        }
                        else {
                            exp.push(IR::Sym(tag.to_owned()));
                            exp.push(node);
                            return Err("Invalid Tag type")
                        }
                    },
                    _ => {
                        exp.push(tag);
                        exp.push(node);
                        return Err("Invalid Tag type")
                    }
                }
            }
            else {
                match node {
                    IR::Sym(ref tag) => {
                        let tag: &str = &tag;
                        match tag {
                            "next:back" => { next = Next::Back },
                            "next:restart" => { next = Next::Restart(None) },
                            "next:exit" => { next = Next::Exit },
                            "next:clear" => { next = Next::Clear },
                            _ => {
                                exp.push(IR::Sym(tag.to_owned()));
                                return Err("Invalid Tag type")
                            },
                        }
                    },
                    _ => {
                        exp.push(node);
                        return Err("Missing Tag type")
                    }
                }
            }
        }
        else { return Err("No Next type found") }

        Ok(next)
    }
}

impl Src {
    pub fn eval<D:Eval> (&self,
                         data: &mut D,
                         def: &mut Def)
                         -> (Vec<Var>,Option<Next>)
    {
        match self {
            &Src::Mut(ref m, ref v, ref a) => {
                match m {
                    &Mut::Add | &Mut::Sub | &Mut::Mul | &Mut::Div => {
                        let mut num = None;

                        let var_name = Var::Sym(v.to_owned());
                        let mut v1 = Var::get_num(&var_name, def);
                        let is_def = v1.is_ok();
                        if !is_def { v1 = Var::get_num(&var_name, data); }

                        if let Ok(v1) = v1 {
                            let var_name = &a[0];
                            let mut v2 = Var::get_num(&var_name, def);
                            if v2.is_err() { v2 = Var::get_num(&var_name, data); }

                            if let Ok(v2) = v2 {
                                match m {
                                    &Mut::Add => {
                                        num = Some(v1+v2);
                                    },
                                    &Mut::Sub => {
                                        num = Some(v1-v2);
                                    },
                                    &Mut::Mul => {
                                        num = Some(v1*v2);
                                    },
                                    &Mut::Div => {
                                        num = Some(v1/v2);
                                    },
                                    _ => {},
                                }
                            }
                        }

                        if let Some(num) = num {
                            if is_def { def.set_path(&v, Var::Num(num)); }
                            else { data.set_path(&v, Var::Num(num)); }
                        }
                    },
                    &Mut::Swap => {
                        let val = a[0].clone();
                        if def.get_path(v).is_some() {
                            def.set_path(v,val);
                        }
                        else { data.set_path(&v, val); }
                    },
                    &Mut::Fn(ref fun) => {
                        let mut args = vec![]; //collect symbols' value
                        for n in a {
                            match n {
                                &Var::Sym(ref n) => {
                                    if let Some(var) = def.get_path(n) {
                                        args.push(var);
                                    }
                                    else {
                                        if let Some(var) = data.get_path(n) {
                                            args.push(var);
                                        }
                                    }
                                },
                                _ => { args.push(n.clone()) }
                            }
                        }

                        if let Some(var) = def.get_path(v) {
                            if let Some(r) = data.call(var, fun, &args) {
                                def.set_path(&v, r);
                            }
                        }
                        else if let Some(var) = data.get_path(&v) {
                            if let Some(r) = data.call(var, fun, &args) {
                                data.set_path(&v, r);
                            }
                        }
                    },
                }

                return (vec![],None)
            }
            &Src::Next(ref next) => {
                return (vec![],Some(next.clone()))
            },
            &Src::Or(ref vars, ref next) => {
                return (vars.clone(), next.clone())
            },
            &Src::Emit(ref vars) => {
                return (vars.clone(),None)
            },
            &Src::Logic(_,_) => {
                return (vec![],None) // logic does not return anything
            },
            &Src::Composite(ref _name, ref x, ref lookups) => {
                // track if any lookups are false or true
                let mut comp_false = false;
                let mut comp_true = false;

                for lookup in lookups.iter() {
                    if let Some(val) = data.get_path(lookup) {
                        match val {
                            Var::Bool(b) => {
                                if b { comp_true = true; }
                                else { comp_false = true; }
                            }
                            _ => { comp_true = true; } //identity/exists, true
                        }
                    }
                }

                match x {
                    &Expect::All => { // all must pass as true
                        if comp_true && !comp_false {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Any => { // first truth passes for set
                        if comp_true {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::None => { // inverse of any, none must be true
                        if !comp_true && comp_false {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Ref(_) => {} // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &Src::If(ref _x, ref _v, ref _next) => {
                // TODO: run logic eval on call

               /* let mut if_value = false;
                match x {
                    &Expect::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &Expect::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &Expect::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &Expect::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if let Some(val) = val {
                            if_value = *val;
                        }
                        else if let Some(val) = def.get_path(lookup) {
                            match val {
                                Var::Bool(v) => { if_value = v; },
                                _ => { if_value = true; }
                            }
                        }
                        else if let Some(val) = data.get_path(lookup) {
                            match val {
                                Var::Bool(v) => { if_value = v; },
                                _ => { if_value = true; }
                            }
                        }
                    },
                }

                if if_value { return ((*v).clone(), next.clone()) }
                else { return (vec![],None) }*/

                return (vec![],None)
            },
            &Src::When(ref _map) => {
                /*for (k, &(ref m, ref v, ref a)) in map.iter() {
                    let mut is_true = false;
                    if let Some(b) = state.get(k) { is_true = *b }
                    if is_true {
                        Src::eval(&Src::Mut(m.clone(), v.clone(), a.clone()), state, data, def);
                    }
                }*/

                return (vec![],None)
            },
        }
    }

    pub fn parse(mut exp: Vec<IR>) -> Result<Src,&'static str> {
        let ir = exp.remove(0);
        match ir {
            IR::Sym(ref sym) => {
                if sym.chars().next() == Some('@') { //mutating statement
                    exp.insert(0,IR::Sym(sym.to_owned()));
                    let (m, v, a) = try!(Mut::parse(&mut exp));
                    return Ok(Src::Mut(m,v,a))
                }
                else if sym == "when" {
                    if exp.len() != 1 { return Err("Invalid WHEN Logic") }
                    if let Ok(mut map) = Parser::parse_map(exp.pop().unwrap()) {
                        let mut when_map: WhenMap = HashMap::new();
                        for (k,mut v) in map.drain() {
                            let v_ir = v.drain(..).map(|n| n.into()).collect();
                            let m = try!(Src::parse(v_ir));
                            match m {
                                Src::Mut(m,v,a) => {
                                    when_map.insert(k, (m,v,a));
                                },
                                _ => { return Err("Invalid WHEN Logic"); }
                            }
                        }

                        if when_map.is_empty() { return Err("Unable to parse WHEN Map into Mut") }
                        Ok(Src::When(when_map))
                    }
                    else { Err(" Invalid WHEN Logic") }
                }
                else if sym == "if" {
                    if exp.len() < 2 { return Err("Invalid IF Logic") }

                    let x = exp.remove(0);
                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::If(Expect::parse(x.into()),
                               v, next.ok()))
                }
                else if sym == "or" {
                    if exp.len() < 1 { return Err("Invalid OR Logic") }

                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::Or(v,next.ok()))
                }
                else if &sym.split_terminator(':').next() == &Some("next") {
                    exp.insert(0, IR::Sym(sym.to_owned()));
                    let next = Next::parse(&mut exp);
                    if let Ok(next) = next {
                        Ok(Src::Next(next))
                    }
                    else { Err("Invalid NEXT Logic") }
                }
                else if sym == "emit" {
                    if exp.len() > 0 {
                        let mut v = vec![];
                        for e in exp.drain(..) {
                            let r = try!(Var::parse(e));
                            v.push(r);
                        }

                        Ok(Src::Emit(v))
                    }
                    else { Err("Missing EMIT Logic") }
                }
                else {
                    let mut keys: Vec<&str> = sym.split_terminator(':').collect();
                    if keys.len() < 2 { // regular logic
                        let r = try!(Logic::parse(exp));
                        Ok(Src::Logic(sym.to_owned(),
                                      r))
                    }
                    else { // composite type
                        let kind = Expect::parse(keys.pop().unwrap().to_owned());
                        match kind { // only formal expected types allowed
                            Expect::Ref(_) => { return Err("Informal Expect found") },
                            _ => {}
                        }

                        let exp = exp.drain(..).map(|n| n.into()).collect();
                        Ok(Src::Composite(keys.pop().unwrap().to_owned(),
                                          kind,
                                          exp))
                    }
                }
            },
            _ => { Err("Encountered Non-Symbol Token") },
        }
    }
}
<commit_msg>add todo<commit_after>use std::collections::HashMap;

use logic::{Logic,Expect};
use eval::Eval;
use var::{Var,Mut};
use parse::{Parser,Map,Def,IR};

/// Source block statement types
#[derive(Debug,PartialEq)]
pub enum Src {
    /// Standard logic, eg: has_sword_item i
    Logic(String, Logic),

    /// References logic in env and emits varkinds
    ///
    /// Logic must resolve to true
    /// eg: if item_logic give_quest
    /// Can optionally end execution and begin next node
    If(Expect, Vec<Var>, Option<Next>),

    /// Or must follow an previous If
    ///
    /// Or only fires when previous If logic fails
    Or(Vec<Var>,Option<Next>),

    /// Just emits variables
    Emit(Vec<Var>),

    /// A composite logic type to group logic statements together
    Composite(String,Expect,Vec<String>),

    /// Ends execution and begins next node
    Next(Next),

    /// Mutate type, var being mutated, argument vars
    Mut(Mut, String, Vec<Var>),

    /// Match-like behavior for Mutations
    ///
    /// Map format should have Logic-Tested for the key
    /// and Mutation Function Signature for the value
    When(WhenMap),
}

/// Internal type to hold a specialized When-Mutate Map
pub type WhenMap = HashMap<String,(Mut,String,Vec<Var>)>;

/// Next-node action types
#[derive(Debug,PartialEq,Clone)]
pub enum Next {
    /// Instantly advances
    Now(String),

    /// Restarts current node, optionally another node -- heads immediately to this node on next evaluation
    Restart(Option<String>),

    /// Heads back to previous node visited
    Back,

    /// Clears out Node stack, pushes current node for further evaluation
    Clear,

    /// Awaits for manual advancement, failure to advance continues current node
    Await(String),

    /// Select from a group, based on decision
    Select(Map),

    /// Exits evaluation completely
    Exit
}
impl Next {
    pub fn parse(exp: &mut Vec<IR>) -> Result<Next,&'static str> {
        let mut select_idx = None;
        for (i,n) in exp.iter().enumerate() {
            match n {
                &IR::Sym(ref s) => {
                    if s == &"next:select" {
                        select_idx = Some(i);
                        break
                    }
                },
                _ => {},
            }
        }

        // handle nested selects as a special case
        if let Some(idx) = select_idx {
            let map_ir = exp.remove(idx+1);
            let _ = exp.remove(idx); // next:select statement
            if let Ok(map) = Parser::parse_map(map_ir) {
                return Ok(Next::Select(map))
            }
            else { return Err("Cannot parse map") }
        }

        let next;
        if let Some(node) = exp.pop() {
            if let Some(tag) = exp.pop() {
                match tag {
                    IR::Sym(tag) => {
                        let mut next_tag = tag.split_terminator(':');
                        let is_next = next_tag.next() == Some("next");

                        if is_next {
                            let next_tag = next_tag.next();
                            match next_tag {
                                Some("now") => { next = Next::Now(node.into()) },
                                Some("await") => { next = Next::Await(node.into()) },
                                Some("restart") => { next = Next::Restart(Some(node.into())) },
                                _ => { return Err("Invalid Next Type Found") },
                            }
                        }
                        else if next_tag.next().is_some() {
                            return Err("Unknown Tag encountered")
                        }
                        else {
                            exp.push(IR::Sym(tag.to_owned()));
                            exp.push(node);
                            return Err("Invalid Tag type")
                        }
                    },
                    _ => {
                        exp.push(tag);
                        exp.push(node);
                        return Err("Invalid Tag type")
                    }
                }
            }
            else {
                match node {
                    IR::Sym(ref tag) => {
                        let tag: &str = &tag;
                        match tag {
                            "next:back" => { next = Next::Back },
                            "next:restart" => { next = Next::Restart(None) },
                            "next:exit" => { next = Next::Exit },
                            "next:clear" => { next = Next::Clear },
                            _ => {
                                exp.push(IR::Sym(tag.to_owned()));
                                return Err("Invalid Tag type")
                            },
                        }
                    },
                    _ => {
                        exp.push(node);
                        return Err("Missing Tag type")
                    }
                }
            }
        }
        else { return Err("No Next type found") }

        Ok(next)
    }
}

impl Src {
    // TODO: only take D or Def, not both
    pub fn eval<D:Eval> (&self,
                         data: &mut D,
                         def: &mut Def)
                         -> (Vec<Var>,Option<Next>)
    {
        match self {
            &Src::Mut(ref m, ref v, ref a) => {
                match m {
                    &Mut::Add | &Mut::Sub | &Mut::Mul | &Mut::Div => {
                        let mut num = None;

                        let var_name = Var::Sym(v.to_owned());
                        let mut v1 = Var::get_num(&var_name, def);
                        let is_def = v1.is_ok();
                        if !is_def { v1 = Var::get_num(&var_name, data); }

                        if let Ok(v1) = v1 {
                            let var_name = &a[0];
                            let mut v2 = Var::get_num(&var_name, def);
                            if v2.is_err() { v2 = Var::get_num(&var_name, data); }

                            if let Ok(v2) = v2 {
                                match m {
                                    &Mut::Add => {
                                        num = Some(v1+v2);
                                    },
                                    &Mut::Sub => {
                                        num = Some(v1-v2);
                                    },
                                    &Mut::Mul => {
                                        num = Some(v1*v2);
                                    },
                                    &Mut::Div => {
                                        num = Some(v1/v2);
                                    },
                                    _ => {},
                                }
                            }
                        }

                        if let Some(num) = num {
                            if is_def { def.set_path(&v, Var::Num(num)); }
                            else { data.set_path(&v, Var::Num(num)); }
                        }
                    },
                    &Mut::Swap => {
                        let val = a[0].clone();
                        if def.get_path(v).is_some() {
                            def.set_path(v,val);
                        }
                        else { data.set_path(&v, val); }
                    },
                    &Mut::Fn(ref fun) => {
                        let mut args = vec![]; //collect symbols' value
                        for n in a {
                            match n {
                                &Var::Sym(ref n) => {
                                    if let Some(var) = def.get_path(n) {
                                        args.push(var);
                                    }
                                    else {
                                        if let Some(var) = data.get_path(n) {
                                            args.push(var);
                                        }
                                    }
                                },
                                _ => { args.push(n.clone()) }
                            }
                        }

                        if let Some(var) = def.get_path(v) {
                            if let Some(r) = data.call(var, fun, &args) {
                                def.set_path(&v, r);
                            }
                        }
                        else if let Some(var) = data.get_path(&v) {
                            if let Some(r) = data.call(var, fun, &args) {
                                data.set_path(&v, r);
                            }
                        }
                    },
                }

                return (vec![],None)
            }
            &Src::Next(ref next) => {
                return (vec![],Some(next.clone()))
            },
            &Src::Or(ref vars, ref next) => {
                return (vars.clone(), next.clone())
            },
            &Src::Emit(ref vars) => {
                return (vars.clone(),None)
            },
            &Src::Logic(_,_) => {
                return (vec![],None) // logic does not return anything
            },
            &Src::Composite(ref _name, ref x, ref lookups) => {
                // track if any lookups are false or true
                let mut comp_false = false;
                let mut comp_true = false;

                for lookup in lookups.iter() {
                    if let Some(val) = data.get_path(lookup) {
                        match val {
                            Var::Bool(b) => {
                                if b { comp_true = true; }
                                else { comp_false = true; }
                            }
                            _ => { comp_true = true; } //identity/exists, true
                        }
                    }
                }

                match x {
                    &Expect::All => { // all must pass as true
                        if comp_true && !comp_false {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Any => { // first truth passes for set
                        if comp_true {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::None => { // inverse of any, none must be true
                        if !comp_true && comp_false {
                            //state.insert(name.clone(),true);
                        }
                    },
                    &Expect::Ref(_) => {} // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &Src::If(ref _x, ref _v, ref _next) => {
                // TODO: run logic eval on call

               /* let mut if_value = false;
                match x {
                    &Expect::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &Expect::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &Expect::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &Expect::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if let Some(val) = val {
                            if_value = *val;
                        }
                        else if let Some(val) = def.get_path(lookup) {
                            match val {
                                Var::Bool(v) => { if_value = v; },
                                _ => { if_value = true; }
                            }
                        }
                        else if let Some(val) = data.get_path(lookup) {
                            match val {
                                Var::Bool(v) => { if_value = v; },
                                _ => { if_value = true; }
                            }
                        }
                    },
                }

                if if_value { return ((*v).clone(), next.clone()) }
                else { return (vec![],None) }*/

                return (vec![],None)
            },
            &Src::When(ref _map) => {
                /*for (k, &(ref m, ref v, ref a)) in map.iter() {
                    let mut is_true = false;
                    if let Some(b) = state.get(k) { is_true = *b }
                    if is_true {
                        Src::eval(&Src::Mut(m.clone(), v.clone(), a.clone()), state, data, def);
                    }
                }*/

                return (vec![],None)
            },
        }
    }

    pub fn parse(mut exp: Vec<IR>) -> Result<Src,&'static str> {
        let ir = exp.remove(0);
        match ir {
            IR::Sym(ref sym) => {
                if sym.chars().next() == Some('@') { //mutating statement
                    exp.insert(0,IR::Sym(sym.to_owned()));
                    let (m, v, a) = try!(Mut::parse(&mut exp));
                    return Ok(Src::Mut(m,v,a))
                }
                else if sym == "when" {
                    if exp.len() != 1 { return Err("Invalid WHEN Logic") }
                    if let Ok(mut map) = Parser::parse_map(exp.pop().unwrap()) {
                        let mut when_map: WhenMap = HashMap::new();
                        for (k,mut v) in map.drain() {
                            let v_ir = v.drain(..).map(|n| n.into()).collect();
                            let m = try!(Src::parse(v_ir));
                            match m {
                                Src::Mut(m,v,a) => {
                                    when_map.insert(k, (m,v,a));
                                },
                                _ => { return Err("Invalid WHEN Logic"); }
                            }
                        }

                        if when_map.is_empty() { return Err("Unable to parse WHEN Map into Mut") }
                        Ok(Src::When(when_map))
                    }
                    else { Err(" Invalid WHEN Logic") }
                }
                else if sym == "if" {
                    if exp.len() < 2 { return Err("Invalid IF Logic") }

                    let x = exp.remove(0);
                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::If(Expect::parse(x.into()),
                               v, next.ok()))
                }
                else if sym == "or" {
                    if exp.len() < 1 { return Err("Invalid OR Logic") }

                    let next = Next::parse(&mut exp);

                    let mut v = vec![];
                    for n in exp.drain(..) {
                        let r = try!(Var::parse(n));
                        v.push(r);
                    }

                    Ok(Src::Or(v,next.ok()))
                }
                else if &sym.split_terminator(':').next() == &Some("next") {
                    exp.insert(0, IR::Sym(sym.to_owned()));
                    let next = Next::parse(&mut exp);
                    if let Ok(next) = next {
                        Ok(Src::Next(next))
                    }
                    else { Err("Invalid NEXT Logic") }
                }
                else if sym == "emit" {
                    if exp.len() > 0 {
                        let mut v = vec![];
                        for e in exp.drain(..) {
                            let r = try!(Var::parse(e));
                            v.push(r);
                        }

                        Ok(Src::Emit(v))
                    }
                    else { Err("Missing EMIT Logic") }
                }
                else {
                    let mut keys: Vec<&str> = sym.split_terminator(':').collect();
                    if keys.len() < 2 { // regular logic
                        let r = try!(Logic::parse(exp));
                        Ok(Src::Logic(sym.to_owned(),
                                      r))
                    }
                    else { // composite type
                        let kind = Expect::parse(keys.pop().unwrap().to_owned());
                        match kind { // only formal expected types allowed
                            Expect::Ref(_) => { return Err("Informal Expect found") },
                            _ => {}
                        }

                        let exp = exp.drain(..).map(|n| n.into()).collect();
                        Ok(Src::Composite(keys.pop().unwrap().to_owned(),
                                          kind,
                                          exp))
                    }
                }
            },
            _ => { Err("Encountered Non-Symbol Token") },
        }
    }
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Cache, Load, LoadError};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }
}

impl<'a, T> Load<'a> for Spline<T> where T: Deserialize {
  type Args = ();

  fn load<P>(path: P, _: &mut Cache<'a>, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys))
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

/// Samplers can sample a spline by providing time. They should be mutable so that they can maintain
/// an internal state for optimization purposes.
#[derive(Copy, Clone)]
pub struct Sampler<'a, T> where T: 'a {
  /// Borrowed spline.
  spline: &'a Spline<T>,
  /// Playback cursor – gives the lower control point index of the current portion of the curve
  /// we’re sampling at.
  cursor: usize
}

impl<'a, T> Sampler<'a, T> where T: 'a {
  pub fn new(spline: &'a Spline<T>) -> Self {
    Sampler {
      spline: spline,
      cursor: 0
    }
  }

  /// Sample a spline at a given time.
  ///
  /// The spline might be altered for optimization purpose, in a way so that next calls to this
  /// function have few work to do.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  ///
  /// # Complexity
  ///
  /// The idea is that if you pass in a continuous ascending time, this function gives a response in
  /// a constant time – *O(1)*. If you pass a stochastic or arbitrary time (for instance for
  /// debugging or for editing purposes), the complexity is linear – *O(N)* on the number of keys.
  pub fn sample(&mut self, t: Time) -> Option<T>
      where T: Interpolate {
    let keys = &self.spline.keys;
    let i = around_search_lower_cp(keys, self.cursor, t);

    // if we’ve found the index, replace the cursor to speed up next searches
    if let Some(cursor) = i {
      self.cursor = cursor;
    }

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time. Continuous version. `i` is the last
// known found index.
fn around_search_lower_cp<T>(cps: &[Key<T>], mut i: usize, t: Time) -> Option<usize> {
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<commit_msg>Added Spline::sampler().<commit_after>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Cache, Load, LoadError};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }

  /// Create a sampler from a spline by borrowing it.
  pub fn sampler(&self) -> Sampler<T> {
    Sampler::new(self)
  }
}

impl<'a, T> Load<'a> for Spline<T> where T: Deserialize {
  type Args = ();

  fn load<P>(path: P, _: &mut Cache<'a>, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys))
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

/// Samplers can sample a spline by providing time. They should be mutable so that they can maintain
/// an internal state for optimization purposes.
#[derive(Copy, Clone)]
pub struct Sampler<'a, T> where T: 'a {
  /// Borrowed spline.
  spline: &'a Spline<T>,
  /// Playback cursor – gives the lower control point index of the current portion of the curve
  /// we’re sampling at.
  cursor: usize
}

impl<'a, T> Sampler<'a, T> where T: 'a {
  pub fn new(spline: &'a Spline<T>) -> Self {
    Sampler {
      spline: spline,
      cursor: 0
    }
  }

  /// Sample a spline at a given time.
  ///
  /// The spline might be altered for optimization purpose, in a way so that next calls to this
  /// function have few work to do.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  ///
  /// # Complexity
  ///
  /// The idea is that if you pass in a continuous ascending time, this function gives a response in
  /// a constant time – *O(1)*. If you pass a stochastic or arbitrary time (for instance for
  /// debugging or for editing purposes), the complexity is linear – *O(N)* on the number of keys.
  pub fn sample(&mut self, t: Time) -> Option<T>
      where T: Interpolate {
    let keys = &self.spline.keys;
    let i = around_search_lower_cp(keys, self.cursor, t);

    // if we’ve found the index, replace the cursor to speed up next searches
    if let Some(cursor) = i {
      self.cursor = cursor;
    }

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time. Continuous version. `i` is the last
// known found index.
fn around_search_lower_cp<T>(cps: &[Key<T>], mut i: usize, t: Time) -> Option<usize> {
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<|endoftext|>


<commit_before>//! Generate update information from dependency information.

use std::rc::Rc;
use std::collections::HashMap;

use semver::Version;

use dependencies;

/// Stores old and new version.
pub struct Bump {
    /// The old version.
    pub old: Version,
    /// The new version.
    pub new: Version,
}

/// Stores update info for dependency.
pub struct Dependency {
    /// The library name.
    pub name: Rc<String>,
    /// Bump info.
    pub bump: Bump,
}

/// Stores information about a package.
pub struct Package {
    /// The package name.
    pub name: Rc<String>,
    /// The order to update library.
    pub order: u32,
    /// Update information.
    pub bump: Bump,
    /// The dependencies.
    pub dependencies: Vec<Dependency>,
}

/// Generates update info.
pub fn generate_update_info_from(dependency_info: &str) -> Result<String, String> {
    use piston_meta::*;

    fn depth_of(
        package: &dependencies::Package,
        depth: &mut HashMap<Rc<String>, u32>,
        dependencies_data: &[dependencies::Package]
    ) -> u32 {
        let d = depth.get(&package.name).map(|d| *d);
        match d {
            None => {
                // The depth of a package equals maximum depth of the dependencies + 1.
                let new_depth: u32 = package.dependencies.iter().map(|dep| {
                        // Get depth of dependency.
                        // If none of the dependencies are listed, treat it as zero.
                        dependencies_data.iter().filter(|p| {
                                p.name == dep.name
                            }).next().map(|p| {
                                depth_of(p, depth, dependencies_data)
                            }).unwrap_or(0)
                    }).max().unwrap_or(0) + 1;
                depth.insert(package.name.clone(), new_depth);
                new_depth
            }
            Some(x) => x
        }
    }

    // Parse and convert to dependencies data.
    let dependencies_meta_syntax = include_str!("../assets/dependencies/syntax.txt");
    let dependencies_meta_rules = stderr_unwrap(dependencies_meta_syntax,
        syntax(dependencies_meta_syntax));
    let dependency_info = stderr_unwrap(dependency_info,
        parse(&dependencies_meta_rules, dependency_info));
    let mut ignored = vec![];
    let dependencies_data = try!(dependencies::convert(&dependency_info, &mut ignored)
        .map_err(|_| String::from("Could not convert dependency info")));

    let mut depth: HashMap<Rc<String>, u32> = HashMap::new();
    for package in &dependencies_data {
        let _depth = depth_of(package, &mut depth, &dependencies_data);
    }

    Ok(String::from(""))
}
<commit_msg>Started on update detection<commit_after>//! Generate update information from dependency information.

use std::rc::Rc;
use std::collections::HashMap;

use semver::Version;

use dependencies;

/// Stores old and new version.
pub struct Bump {
    /// The old version.
    pub old: Version,
    /// The new version.
    pub new: Version,
}

/// Stores update info for dependency.
pub struct Dependency {
    /// The library name.
    pub name: Rc<String>,
    /// Bump info.
    pub bump: Bump,
}

/// Stores information about a package.
pub struct Package {
    /// The package name.
    pub name: Rc<String>,
    /// The order to update library.
    pub order: u32,
    /// Update information.
    pub bump: Bump,
    /// The dependencies.
    pub dependencies: Vec<Dependency>,
}

/// Generates update info.
pub fn generate_update_info_from(dependency_info: &str) -> Result<String, String> {
    use piston_meta::*;

    fn depth_of(
        package: &dependencies::Package,
        depth: &mut HashMap<Rc<String>, u32>,
        dependencies_data: &[dependencies::Package]
    ) -> u32 {
        let d = depth.get(&package.name).map(|d| *d);
        match d {
            None => {
                // The depth of a package equals maximum depth of the dependencies + 1.
                let new_depth: u32 = package.dependencies.iter().map(|dep| {
                        // Get depth of dependency.
                        // If none of the dependencies are listed, treat it as zero.
                        dependencies_data.iter().filter(|p| {
                                p.name == dep.name
                            }).next().map(|p| {
                                depth_of(p, depth, dependencies_data)
                            }).unwrap_or(0)
                    }).max().unwrap_or(0) + 1;
                depth.insert(package.name.clone(), new_depth);
                new_depth
            }
            Some(x) => x
        }
    }

    // Parse and convert to dependencies data.
    let dependencies_meta_syntax = include_str!("../assets/dependencies/syntax.txt");
    let dependencies_meta_rules = stderr_unwrap(dependencies_meta_syntax,
        syntax(dependencies_meta_syntax));
    let dependency_info = stderr_unwrap(dependency_info,
        parse(&dependencies_meta_rules, dependency_info));
    let mut ignored = vec![];
    let dependencies_data = try!(dependencies::convert(&dependency_info, &mut ignored)
        .map_err(|_| String::from("Could not convert dependency info")));

    // Store the depths of libraries.
    let mut depths: HashMap<Rc<String>, u32> = HashMap::new();
    for package in &dependencies_data {
        let _depth = depth_of(package, &mut depths, &dependencies_data);
    }

    let mut new_versions: HashMap<Rc<String>, Version> = HashMap::new();
    for package in &dependencies_data {
        // Get latest version used by any dependency.
        for dep in &package.dependencies {
            let version = try!(Version::parse(&dep.version)
                .map_err(|_| format!("Could not parse version `{}` for `{}`",
                    &dep.version, &dep.name)));
            let v = new_versions.get(&dep.name).map(|v| v.clone());
            match v {
                None => {
                    new_versions.insert(dep.name.clone(), version);
                }
                Some(v) => {
                    if v < version {
                        new_versions.insert(dep.name.clone(), version);
                    }
                }
            }
        }
    }

    // Overwrite the versions used by packages.
    for package in &dependencies_data {
        let version = try!(Version::parse(&package.version)
            .map_err(|_| format!("Could not parse version `{}` for `{}`",
                &package.version, &package.name)));
        new_versions.insert(package.name.clone(), version);
    }

    Ok(String::from(""))
}
<|endoftext|>


<commit_before>//! Bootstrap your application!
//!
//! This module is used to create an application with spectra. Its aim is to quickly setup a spectra
//! app so that you can start working on interesting things.
use clap::{App, Arg};
use luminance_glfw;
pub use luminance_glfw::{Device as DeviceTrait, GLFWDeviceError, Key, MouseButton, WindowDim, WindowOpt};
use std::thread;
use std::time::{Duration, Instant};

pub use sys::event::WindowEvent;

pub type Time = f64;

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  raw: luminance_glfw::GLFWDevice,
  /// Some kind of epoch start the application started at.
  start_time: Instant
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// > Note: see `bootstrap!` macro for a better usage.
  pub fn new(def_width: u32,
             def_height: u32,
             version: &str,
             author: &str,
             title: &str,
             win_opt: WindowOpt)
             -> Result<Self, GLFWDeviceError> {
    let options = App::new(title)
      .version(version)
      .author(author)
      .arg(Arg::with_name("width")
           .short("w")
           .long("width")
           .value_name("WIDTH")
           .help("Sets the width of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("height")
           .short("h")
           .long("height")
           .value_name("HEIGHT")
           .help("Sets the height of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("fullscreen")
           .short("f")
           .long("fullscreen")
           .value_name("FULLSCREEN")
           .help("Sets the viewport to be displayed in fullscreen mode")
           .takes_value(false))
      .get_matches();

    let width = options.value_of("width").map(|s| s.parse().unwrap_or(def_width)).unwrap_or(def_width);
    let height = options.value_of("height").map(|s| s.parse().unwrap_or(def_height)).unwrap_or(def_height);
    let fullscreen = options.is_present("fullscreen");

    // build the WindowDim
    let win_dim = if fullscreen {
      if options.is_present("width") && options.is_present("height") {
        WindowDim::FullscreenRestricted(width, height)
      } else {
        WindowDim::Fullscreen
      }
    } else {
      WindowDim::Windowed(width, height)
    };

    info!("{} starting", title);
    info!("window mode: {:?}", win_dim);
    info!("window options: {:?}", win_opt);

    let dev = luminance_glfw::GLFWDevice::new(win_dim, title, win_opt)?;

    info!("bootstrapping finished");

    Ok(Device {
      raw: dev,
      start_time: Instant::now()
    })
  }

  /// Size of the attached window.
  #[inline]
  pub fn size(&self) -> [u32; 2] {
    self.raw.size()
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Get the last event and pop it from the event queue. Supposed to be called in a loop.
  pub fn events<'a>(&'a mut self) -> impl Iterator<Item = WindowEvent> + 'a {
    self.raw.events()
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<FPS, R>(&mut self, fps: FPS, mut draw_frame: R) -> bool where FPS: Into<Option<u32>>, R: FnMut(Time) {
    let t = self.time();

    self.raw.draw(|| {
      draw_frame(t);
    });

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps.into() {
      let fps = fps as f64;
      let max_time = 1. / fps;
      let elapsed_time = self.time() - t;

      if elapsed_time < max_time {
        let sleep_time = max_time - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

#[macro_export]
macro_rules! bootstrap {
  ($def_width:expr, $def_height:expr, $win_opt:expr) => {{
    $crate::sys::bootstrap::Device::new($def_width,
                                        $def_height,
                                        crate_version!(),
                                        crate_authors!(),
                                        crate_name!(),
                                        $win_opt)
  }}
}
<commit_msg>Expose a framerate limit.<commit_after>//! Bootstrap your application!
//!
//! This module is used to create an application with spectra. Its aim is to quickly setup a spectra
//! app so that you can start working on interesting things.
use clap::{App, Arg};
use luminance_glfw;
pub use luminance_glfw::{Device as DeviceTrait, GLFWDeviceError, Key, MouseButton, WindowDim, WindowOpt};
use std::thread;
use std::time::{Duration, Instant};

pub use sys::event::WindowEvent;

pub type Time = f64;

pub type Fps = f64;

/// Device object.
///
/// Upon bootstrapping, this type is created to add interaction and context handling.
pub struct Device {
  raw: luminance_glfw::GLFWDevice,
  /// Some kind of epoch start the application started at.
  start_time: Instant,
  /// Frame rate limit to use when rendering. If none, no limit.
  framerate_limit_ms: Option<Fps>
}

impl Device {
  /// Entry point.
  ///
  /// This function is the first one you have to call before anything else related to this crate.
  ///
  /// > Note: see `bootstrap!` macro for a better usage.
  pub fn new(def_width: u32,
             def_height: u32,
             version: &str,
             author: &str,
             title: &str,
             win_opt: WindowOpt)
             -> Result<Self, GLFWDeviceError> {
    let options = App::new(title)
      .version(version)
      .author(author)
      .arg(Arg::with_name("width")
           .short("w")
           .long("width")
           .value_name("WIDTH")
           .help("Set the width of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("height")
           .short("h")
           .long("height")
           .value_name("HEIGHT")
           .help("Set the height of the viewport used for render")
           .takes_value(true))
      .arg(Arg::with_name("fullscreen")
           .short("f")
           .long("fullscreen")
           .value_name("FULLSCREEN")
           .help("Set the viewport to be displayed in fullscreen mode")
           .takes_value(false))
      .arg(Arg::with_name("framerate-limit")
           .short("r")
           .long("limit-framerate-to")
           .value_name("FRAMERATE_LIMIT")
           .help("Set the framerate limit")
           .takes_value(false))
      .get_matches();

    let width = options.value_of("width").map(|s| s.parse().unwrap_or(def_width)).unwrap_or(def_width);
    let height = options.value_of("height").map(|s| s.parse().unwrap_or(def_height)).unwrap_or(def_height);
    let fullscreen = options.is_present("fullscreen");
    let framerate_limit_hz: Option<u16> = options.value_of("framerate-limit").and_then(|l| l.parse().ok());
    let framerate_limit_ms = framerate_limit_hz.map(|hz| 1. / (hz as f64));

    // build the WindowDim
    let win_dim = if fullscreen {
      if options.is_present("width") && options.is_present("height") {
        WindowDim::FullscreenRestricted(width, height)
      } else {
        WindowDim::Fullscreen
      }
    } else {
      WindowDim::Windowed(width, height)
    };

    info!("{} starting", title);
    info!("window mode: {:?}", win_dim);
    info!("window options: {:?}", win_opt);

    let dev = luminance_glfw::GLFWDevice::new(win_dim, title, win_opt)?;

    info!("bootstrapping finished");

    Ok(Device {
      raw: dev,
      start_time: Instant::now(),
      framerate_limit_ms
    })
  }

  /// Size of the attached window.
  #[inline]
  pub fn size(&self) -> [u32; 2] {
    self.raw.size()
  }

  /// Current time, starting from the beginning of the creation of that object.
  pub fn time(&self) -> f64 {
    let elapsed = Instant::now() - self.start_time;
    elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
  }

  /// Get the last event and pop it from the event queue. Supposed to be called in a loop.
  pub fn events<'a>(&'a mut self) -> impl Iterator<Item = WindowEvent> + 'a {
    self.raw.events()
  }

  /// Step function.
  ///
  /// This function provides two features:
  ///
  /// - it runs a *drawer* function, responsible of rendering a single frame, by passing it the
  ///   current time
  /// - it performs process idleing if you have requested a certain *framerate* – frame per second.
  ///
  /// The second feature is very neat because it lets you handle the scheduler off your application
  /// and then contribute to better CPU usage.
  ///
  /// > Note: if you pass `None`, no idleing will take place. However, you might be blocked by the
  /// *VSync* if enabled in your driver.
  pub fn step<R>(&mut self, mut draw_frame: R) -> bool where R: FnMut(Time) {
    let t = self.time();

    self.raw.draw(|| {
      draw_frame(t);
    });

    // wait for next frame according to the wished FPS
    if let Some(framerate_limit_ms) = self.framerate_limit_ms {
      let elapsed_time = self.time() - t;

      if elapsed_time < framerate_limit_ms {
        let sleep_time = framerate_limit_ms - elapsed_time;
        thread::sleep(Duration::from_millis((sleep_time * 1e3) as u64));
      }
    }

    true
  }
}

#[macro_export]
macro_rules! bootstrap {
  ($def_width:expr, $def_height:expr, $win_opt:expr) => {{
    $crate::sys::bootstrap::Device::new($def_width,
                                        $def_height,
                                        crate_version!(),
                                        crate_authors!(),
                                        crate_name!(),
                                        $win_opt)
  }}
}
<|endoftext|>


<commit_before>// Uncomment the following line to disable unstable warnings:
// #![allow(unstable)]

#![feature(plugin)]
#[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;
use std::ascii::AsciiExt;
use std::collections;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::io;
use std::io::{BufferedReader, File, IoResult};

pub mod config;
pub mod btree_map;

fn do_work(cfg: &config::Config) -> IoResult<()> {
    // Open input and output files
    let mut readers = vec![];
    if cfg.input.is_empty() {
        readers.push(BufferedReader::new(Box::new(io::stdin()) as Box<Reader>));
    } else {
        for name in cfg.input.iter() {
            let file = try!(File::open(&Path::new(name.as_slice())));
            readers.push(BufferedReader::new(Box::new(file) as Box<Reader>));
        }
    }
    let mut writer = match cfg.output {
        Some(ref x) => { Box::new(try!(File::create(&Path::new(x.as_slice())))) as Box<Writer> }
        None => { Box::new(io::stdout()) as Box<Writer> }
    };

    // Parse words
    let mut map = collections::HashMap::<String, u32>::new();
    // let mut map = btree_map::BTreeMap::<String, u32>::new();
    let re = regex!(r"\w+");
    // let re = Regex::new(r"\w+").unwrap();
    for reader in readers.iter_mut() {
        for line in reader.lines() {
            for caps in re.captures_iter(line.unwrap().as_slice()) {
                if let Some(cap) = caps.at(0) {
                    let word = match cfg.ignore_case {
                        true  => cap.to_ascii_lowercase(),
                        false => cap.to_string(),
                    };
                    match map.entry(word) {
                        Occupied(mut view) => { *view.get_mut() += 1; }
                        Vacant(view) => { view.insert(1); }
                    }
                }
            }
        }
    }

    // Write counts
    let mut words: Vec<&String> = map.keys().collect();
    words.sort();
    for word in words.iter() {
        if let Some(count) = map.get(*word) {
            let line = format!("{}\t{}\n", count, word);
            try!(writer.write(line.as_bytes()));
        }
    }
    Ok(())
}

#[cfg(not(test))]
fn main() {
    let cfg = match config::get_config(std::os::args()) {
        Ok(c) => c,
        Err(usage) => {
            println!("{}", usage);
            return;
        }
    };
    do_work(&cfg).unwrap();
}

#[test]
fn test_do_work() {
    let bad_filename = "/..no-such-file..";
    let cfg = config::Config {
        input: vec![bad_filename.to_string()],
        output: None,
        ignore_case: false,
    };
    match do_work(&cfg) {
        // should fail for bad input file (couldn't open file ... path=/..no-such-file..; ...)
        Err(e) => assert!(format!("{}", e).as_slice().contains(bad_filename), format!("{}", e)),
        _ => panic!()
    }
}

<commit_msg>Use "[a-zA-Z0-9_]+" in addition to "\w+"<commit_after>// Uncomment the following line to disable unstable warnings:
// #![allow(unstable)]

#![feature(plugin)]
#[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;
// use regex::Regex;
use std::ascii::AsciiExt;
use std::collections;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::io;
use std::io::{BufferedReader, File, IoResult};

pub mod config;
pub mod btree_map;

fn do_work(cfg: &config::Config) -> IoResult<()> {
    // Open input and output files
    let mut readers = vec![];
    if cfg.input.is_empty() {
        readers.push(BufferedReader::new(Box::new(io::stdin()) as Box<Reader>));
    } else {
        for name in cfg.input.iter() {
            let file = try!(File::open(&Path::new(name.as_slice())));
            readers.push(BufferedReader::new(Box::new(file) as Box<Reader>));
        }
    }
    let mut writer = match cfg.output {
        Some(ref x) => { Box::new(try!(File::create(&Path::new(x.as_slice())))) as Box<Writer> }
        None => { Box::new(io::stdout()) as Box<Writer> }
    };

    // Parse words
    let mut map = collections::HashMap::<String, u32>::new();
    // let mut map = btree_map::BTreeMap::<String, u32>::new();
    let re = regex!(r"\w+");
    // let re = Regex::new(r"\w+").unwrap();
    // let re = regex!(r"[a-zA-Z0-9_]+");
    // let re = Regex::new(r"[a-zA-Z0-9_]+").unwrap();
    for reader in readers.iter_mut() {
        for line in reader.lines() {
            for caps in re.captures_iter(line.unwrap().as_slice()) {
                if let Some(cap) = caps.at(0) {
                    let word = match cfg.ignore_case {
                        true  => cap.to_ascii_lowercase(),
                        false => cap.to_string(),
                    };
                    match map.entry(word) {
                        Occupied(mut view) => { *view.get_mut() += 1; }
                        Vacant(view) => { view.insert(1); }
                    }
                }
            }
        }
    }

    // Write counts
    let mut words: Vec<&String> = map.keys().collect();
    words.sort();
    for word in words.iter() {
        if let Some(count) = map.get(*word) {
            let line = format!("{}\t{}\n", count, word);
            try!(writer.write(line.as_bytes()));
        }
    }
    Ok(())
}

#[cfg(not(test))]
fn main() {
    let cfg = match config::get_config(std::os::args()) {
        Ok(c) => c,
        Err(usage) => {
            println!("{}", usage);
            return;
        }
    };
    do_work(&cfg).unwrap();
}

#[test]
fn test_do_work() {
    let bad_filename = "/..no-such-file..";
    let cfg = config::Config {
        input: vec![bad_filename.to_string()],
        output: None,
        ignore_case: false,
    };
    match do_work(&cfg) {
        // should fail for bad input file (couldn't open file ... path=/..no-such-file..; ...)
        Err(e) => assert!(format!("{}", e).as_slice().contains(bad_filename), format!("{}", e)),
        _ => panic!()
    }
}

<|endoftext|>