<commit_before>/*
  Basic interval implementation and other common functions/data structures
*/
#![feature(float_extras)]

// External libraries
use std::cmp::{PartialOrd, Ordering, PartialEq, Ord};
use std::f64::{NEG_INFINITY, INFINITY};

// Internal libraries
extern crate gr;
use gr::GI;

// Datatypes
pub type Flt = f64;
pub static INF:  Flt = INFINITY;
pub static NINF: Flt = NEG_INFINITY;

#[macro_export]
macro_rules! max {
    ($x:expr) => {{ $x }};
    ($x:expr, $($y:expr),* ) => {{
        let mut max = $x;
        $(
            max = if max > $y {max} else {$y};
        )*
        max
    }}
}

#[macro_export]
macro_rules! min {
    ($x:expr) => {{ $x }};
    ( $x:expr, $($y:expr),*) => {{
        let mut min = $x;
        $(
            min = if min < $y {min} else {$y};
        )*
        min
    }}
}

// Evolutionary algo
#[derive(Debug, Copy, Clone)]
pub struct Parameters {
    pub population:usize,
    pub selection: usize,
    pub elitism:   usize,
    pub mutation:    Flt,
    pub crossover:   Flt,
}
// Evolutionary algo end

// Quple
// Data structure for insertion of a box into a priority queue
#[derive(Clone)]
pub struct Quple {
    pub p: Flt,
    pub pf: u32,
    pub data: Vec<GI>,
    pub fdata: GI
}

// Allow ordering of Quples
impl PartialEq for Quple {
    fn eq(&self, other: &Quple) -> bool {
        self.pf == other.pf
    }
}

impl Eq for Quple { }

impl PartialOrd for Quple {
    fn partial_cmp(&self, other: &Quple) -> Option<Ordering> {
        if self.p < other.p {
            Some(Ordering::Less)
        }
        else if self.pf < other.pf {
            Some(Ordering::Greater)
        }
        else {
            Some(Ordering::Greater)
        }
    }
}

impl Ord for Quple {
    fn cmp(&self, other: &Quple) -> Ordering {
        if self.p < other.p {
            Ordering::Less
        }
        else if self.pf < other.pf {
            Ordering::Greater
        }
        else if self.pf == other.pf {
            Ordering::Equal
        }
        else {
            Ordering::Greater
        }
    }
}
// End Quple ordering.
// End Quple

pub fn eps_tol(x: f64, y: f64, tol: f64) -> bool {
    let (_,exp_x,_) = x.integer_decode();
    let xe = (2.0f64).powi(exp_x as i32);
    return y - x <= tol.max(xe);
}
<commit_msg>Added predicate for relative output error for bounding<commit_after>/*
Basic interval implementation and other common functions/data structures
 */
#![feature(float_extras)]

// External libraries
use std::cmp::{PartialOrd, Ordering, PartialEq, Ord};
use std::f64::{NEG_INFINITY, INFINITY};

// Internal libraries
extern crate gr;
use gr::GI;

// Datatypes
pub type Flt = f64;
pub static INF:  Flt = INFINITY;
pub static NINF: Flt = NEG_INFINITY;

#[macro_export]
macro_rules! max {
    ($x:expr) => {{ $x }};
    ($x:expr, $($y:expr),* ) => {{
        let mut max = $x;
        $(
            max = if max > $y {max} else {$y};
        )*
            max
    }}
}

#[macro_export]
macro_rules! min {
    ($x:expr) => {{ $x }};
    ( $x:expr, $($y:expr),*) => {{
        let mut min = $x;
        $(
            min = if min < $y {min} else {$y};
        )*
            min
    }}
}

// Evolutionary algo
#[derive(Debug, Copy, Clone)]
pub struct Parameters {
    pub population:usize,
    pub selection: usize,
    pub elitism:   usize,
    pub mutation:    Flt,
    pub crossover:   Flt,
}
// Evolutionary algo end

// Quple
// Data structure for insertion of a box into a priority queue
#[derive(Clone)]
pub struct Quple {
    pub p: Flt,
    pub pf: u32,
    pub data: Vec<GI>,
    pub fdata: GI
}

// Allow ordering of Quples
impl PartialEq for Quple {
    fn eq(&self, other: &Quple) -> bool {
        if self.pf == other.pf &&
            self.p == other.p {
                return true;
            }
        return false;
    }
}

impl Eq for Quple { }

impl PartialOrd for Quple {
    fn partial_cmp(&self, other: &Quple) -> Option<Ordering> {
        // This element is greater than the other element
        if self.pf < other.pf {
            return Some(Ordering::Greater);
        }
        else if self.pf == other.pf {
            return self.p.partial_cmp(&other.p);
        }
        else {
            return Some(Ordering::Less);
        }
    }
}

impl Ord for Quple {
    fn cmp(&self, other: &Quple) -> Ordering {
        if self.pf < other.pf {
            return Ordering::Greater;
        }
        else if self.pf == other.pf {
            if self.p > other.p {
                return Ordering::Greater;
            }
            else if self.p == other.p {
                return Ordering::Equal;
            }
            else {
                return Ordering::Less;
            }
        }
        else {
            return Ordering::Less;
        }
    }
}
// End Quple ordering.
// End Quple

pub fn eps_tol(fx: GI, est: f64, e_f: f64, e_f_r: f64) -> bool {
    (fx.upper() - est).abs() <= e_f_r*est +  e_f
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Result};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Orientation {
  Right,
  UpRight,
  Up,
  UpLeft,
  Left,
  DownLeft,
  Down,
  DownRight,
  Still,
}

impl Display for Orientation {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Orientation::Right => write!(f, "Right"),
      Orientation::UpRight => write!(f, "UpRight"),
      Orientation::Up => write!(f, "Up"),
      Orientation::UpLeft => write!(f, "UpLeft"),
      Orientation::Left => write!(f, "Left"),
      Orientation::DownLeft => write!(f, "DownLeft"),
      Orientation::Down => write!(f, "Down"),
      Orientation::DownRight => write!(f, "DownRight"),
      Orientation::Still => write!(f, "Still"),
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Stance {
  Walking = 0,
  Firing = 1,
  Still = 2,
}

impl Display for Stance {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Stance::Walking => write!(f, "0"),
      Stance::Firing => write!(f, "1"),
      Stance::Still => write!(f, "2"),
    }
  }
}

<commit_msg>Update Stance enum and add new stances "NormalDeath" & "CriticalDeath"<commit_after>use std::fmt::{Display, Formatter, Result};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Orientation {
  Right,
  UpRight,
  Up,
  UpLeft,
  Left,
  DownLeft,
  Down,
  DownRight,
  Still,
}

impl Display for Orientation {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Orientation::Right => write!(f, "Right"),
      Orientation::UpRight => write!(f, "UpRight"),
      Orientation::Up => write!(f, "Up"),
      Orientation::UpLeft => write!(f, "UpLeft"),
      Orientation::Left => write!(f, "Left"),
      Orientation::DownLeft => write!(f, "DownLeft"),
      Orientation::Down => write!(f, "Down"),
      Orientation::DownRight => write!(f, "DownRight"),
      Orientation::Still => write!(f, "Still"),
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Stance {
  Walking,
  Firing,
  Still,
  NormalDeath,
  CriticalDeath,
}

impl Display for Stance {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Stance::Walking => write!(f, "Walking"),
      Stance::Firing => write!(f, "Firing"),
      Stance::Still => write!(f, "Still"),
      Stance::NormalDeath => write!(f, "NormalDeath"),
      Stance::CriticalDeath => write!(f, "CriticalDeath"),
    }
  }
}

<|endoftext|>


<commit_before>use super::ExtractedSyntaxGrammar;
use crate::error::{Error, Result};
use crate::generate::rules::Symbol;
use crate::generate::grammars::{
    Production, ProductionStep, SyntaxGrammar, SyntaxVariable, Variable,
};
use crate::generate::rules::{Alias, Associativity, Rule};

struct RuleFlattener {
    production: Production,
    precedence_stack: Vec<i32>,
    associativity_stack: Vec<Associativity>,
    alias_stack: Vec<Alias>,
}

impl RuleFlattener {
    fn new() -> Self {
        Self {
            production: Production {
                steps: Vec::new(),
                dynamic_precedence: 0,
            },
            precedence_stack: Vec::new(),
            associativity_stack: Vec::new(),
            alias_stack: Vec::new(),
        }
    }

    fn flatten(mut self, rule: Rule) -> Production {
        self.apply(rule, true);
        self.production
    }

    fn apply(&mut self, rule: Rule, at_end: bool) {
        match rule {
            Rule::Seq(members) => {
                let last_index = members.len() - 1;
                for (i, member) in members.into_iter().enumerate() {
                    self.apply(member, i == last_index && at_end);
                }
            }
            Rule::Metadata { rule, params } => {
                let mut has_precedence = false;
                if let Some(precedence) = params.precedence {
                    has_precedence = true;
                    self.precedence_stack.push(precedence);
                }

                let mut has_associativity = false;
                if let Some(associativity) = params.associativity {
                    has_associativity = true;
                    self.associativity_stack.push(associativity);
                }

                let mut has_alias = false;
                if let Some(alias) = params.alias {
                    has_alias = true;
                    self.alias_stack.push(alias);
                }

                if params.dynamic_precedence.abs() > self.production.dynamic_precedence.abs() {
                    self.production.dynamic_precedence = params.dynamic_precedence;
                }

                self.apply(*rule, at_end);

                if has_precedence {
                    self.precedence_stack.pop();
                    if !at_end {
                        self.production.steps.last_mut().unwrap().precedence =
                            self.precedence_stack.last().cloned().unwrap_or(0);
                    }
                }

                if has_associativity {
                    self.associativity_stack.pop();
                    if !at_end {
                        self.production.steps.last_mut().unwrap().associativity =
                            self.associativity_stack.last().cloned();
                    }
                }

                if has_alias {
                    self.alias_stack.pop();
                }
            }
            Rule::Symbol(symbol) => {
                self.production.steps.push(ProductionStep {
                    symbol,
                    precedence: self.precedence_stack.last().cloned().unwrap_or(0),
                    associativity: self.associativity_stack.last().cloned(),
                    alias: self.alias_stack.last().cloned(),
                });
            }
            _ => (),
        }
    }
}

fn extract_choices(rule: Rule) -> Vec<Rule> {
    match rule {
        Rule::Seq(elements) => {
            let mut result = vec![Rule::Blank];
            for element in elements {
                let extraction = extract_choices(element);
                let mut next_result = Vec::new();
                for entry in result {
                    for extraction_entry in extraction.iter() {
                        next_result.push(Rule::Seq(vec![entry.clone(), extraction_entry.clone()]));
                    }
                }
                result = next_result;
            }
            result
        }
        Rule::Choice(elements) => {
            let mut result = Vec::new();
            for element in elements {
                for rule in extract_choices(element) {
                    result.push(rule);
                }
            }
            result
        }
        Rule::Metadata { rule, params } => extract_choices(*rule)
            .into_iter()
            .map(|rule| Rule::Metadata {
                rule: Box::new(rule),
                params: params.clone(),
            })
            .collect(),
        _ => vec![rule],
    }
}

fn flatten_variable(variable: Variable) -> Result<SyntaxVariable> {
    let mut productions = Vec::new();
    for rule in extract_choices(variable.rule) {
        let production = RuleFlattener::new().flatten(rule);
        if !productions.contains(&production) {
            productions.push(production);
        }
    }
    Ok(SyntaxVariable {
        name: variable.name,
        kind: variable.kind,
        productions,
    })
}

fn symbol_is_used(variables: &Vec<SyntaxVariable>, symbol: Symbol) -> bool {
    for variable in variables {
        for production in &variable.productions {
            for step in &production.steps {
                if step.symbol == symbol {
                    return true;
                }
            }
        }
    }
    false
}

pub(super) fn flatten_grammar(grammar: ExtractedSyntaxGrammar) -> Result<SyntaxGrammar> {
    let mut variables = Vec::new();
    for variable in grammar.variables {
        variables.push(flatten_variable(variable)?);
    }
    for (i, variable) in variables.iter().enumerate() {
        for production in &variable.productions {
            if production.steps.is_empty() && symbol_is_used(&variables, Symbol::non_terminal(i)) {
                return Err(Error(format!(
                    "The rule `{}` matches the empty string.

Tree-sitter does not support syntactic rules that match the empty string
unless they are used only as the grammar's start rule.
",
                    variable.name
                )));
            }
        }
    }
    Ok(SyntaxGrammar {
        extra_tokens: grammar.extra_tokens,
        expected_conflicts: grammar.expected_conflicts,
        variables_to_inline: grammar.variables_to_inline,
        external_tokens: grammar.external_tokens,
        word_token: grammar.word_token,
        variables,
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::generate::grammars::VariableType;
    use crate::generate::rules::Symbol;

    #[test]
    fn test_flatten_grammar() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::seq(vec![
                Rule::non_terminal(1),
                Rule::prec_left(
                    101,
                    Rule::seq(vec![
                        Rule::non_terminal(2),
                        Rule::choice(vec![
                            Rule::prec_right(
                                102,
                                Rule::seq(vec![Rule::non_terminal(3), Rule::non_terminal(4)]),
                            ),
                            Rule::non_terminal(5),
                        ]),
                        Rule::non_terminal(6),
                    ]),
                ),
                Rule::non_terminal(7),
            ]),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![
                Production {
                    dynamic_precedence: 0,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(3))
                            .with_prec(102, Some(Associativity::Right)),
                        ProductionStep::new(Symbol::non_terminal(4))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ]
                },
                Production {
                    dynamic_precedence: 0,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(5))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ]
                },
            ]
        );
    }

    #[test]
    fn test_flatten_grammar_with_maximum_dynamic_precedence() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::seq(vec![
                Rule::non_terminal(1),
                Rule::prec_dynamic(
                    101,
                    Rule::seq(vec![
                        Rule::non_terminal(2),
                        Rule::choice(vec![
                            Rule::prec_dynamic(
                                102,
                                Rule::seq(vec![Rule::non_terminal(3), Rule::non_terminal(4)]),
                            ),
                            Rule::non_terminal(5),
                        ]),
                        Rule::non_terminal(6),
                    ]),
                ),
                Rule::non_terminal(7),
            ]),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![
                Production {
                    dynamic_precedence: 102,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2)),
                        ProductionStep::new(Symbol::non_terminal(3)),
                        ProductionStep::new(Symbol::non_terminal(4)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ],
                },
                Production {
                    dynamic_precedence: 101,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2)),
                        ProductionStep::new(Symbol::non_terminal(5)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ],
                },
            ]
        );
    }

    #[test]
    fn test_flatten_grammar_with_final_precedence() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::prec_left(
                101,
                Rule::seq(vec![Rule::non_terminal(1), Rule::non_terminal(2)]),
            ),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![Production {
                dynamic_precedence: 0,
                steps: vec![
                    ProductionStep::new(Symbol::non_terminal(1))
                        .with_prec(101, Some(Associativity::Left)),
                    ProductionStep::new(Symbol::non_terminal(2))
                        .with_prec(101, Some(Associativity::Left)),
                ]
            }]
        );

        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::prec_left(101, Rule::seq(vec![Rule::non_terminal(1)])),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![Production {
                dynamic_precedence: 0,
                steps: vec![ProductionStep::new(Symbol::non_terminal(1))
                    .with_prec(101, Some(Associativity::Left)),]
            }]
        );
    }
}
<commit_msg>Fix edge case in flatten rule<commit_after>use super::ExtractedSyntaxGrammar;
use crate::error::{Error, Result};
use crate::generate::rules::Symbol;
use crate::generate::grammars::{
    Production, ProductionStep, SyntaxGrammar, SyntaxVariable, Variable,
};
use crate::generate::rules::{Alias, Associativity, Rule};

struct RuleFlattener {
    production: Production,
    precedence_stack: Vec<i32>,
    associativity_stack: Vec<Associativity>,
    alias_stack: Vec<Alias>,
}

impl RuleFlattener {
    fn new() -> Self {
        Self {
            production: Production {
                steps: Vec::new(),
                dynamic_precedence: 0,
            },
            precedence_stack: Vec::new(),
            associativity_stack: Vec::new(),
            alias_stack: Vec::new(),
        }
    }

    fn flatten(mut self, rule: Rule) -> Production {
        self.apply(rule, true);
        self.production
    }

    fn apply(&mut self, rule: Rule, at_end: bool) -> bool {
        match rule {
            Rule::Seq(members) => {
                let mut result = false;
                let last_index = members.len() - 1;
                for (i, member) in members.into_iter().enumerate() {
                    result |= self.apply(member, i == last_index && at_end);
                }
                result
            }
            Rule::Metadata { rule, params } => {
                let mut has_precedence = false;
                if let Some(precedence) = params.precedence {
                    has_precedence = true;
                    self.precedence_stack.push(precedence);
                }

                let mut has_associativity = false;
                if let Some(associativity) = params.associativity {
                    has_associativity = true;
                    self.associativity_stack.push(associativity);
                }

                let mut has_alias = false;
                if let Some(alias) = params.alias {
                    has_alias = true;
                    self.alias_stack.push(alias);
                }

                if params.dynamic_precedence.abs() > self.production.dynamic_precedence.abs() {
                    self.production.dynamic_precedence = params.dynamic_precedence;
                }

                let did_push = self.apply(*rule, at_end);

                if has_precedence {
                    self.precedence_stack.pop();
                    if did_push && !at_end {
                        self.production.steps.last_mut().unwrap().precedence =
                            self.precedence_stack.last().cloned().unwrap_or(0);
                    }
                }

                if has_associativity {
                    self.associativity_stack.pop();
                    if did_push && !at_end {
                        self.production.steps.last_mut().unwrap().associativity =
                            self.associativity_stack.last().cloned();
                    }
                }

                if has_alias {
                    self.alias_stack.pop();
                }

                did_push
            }
            Rule::Symbol(symbol) => {
                self.production.steps.push(ProductionStep {
                    symbol,
                    precedence: self.precedence_stack.last().cloned().unwrap_or(0),
                    associativity: self.associativity_stack.last().cloned(),
                    alias: self.alias_stack.last().cloned(),
                });
                true
            }
            _ => false,
        }
    }
}

fn extract_choices(rule: Rule) -> Vec<Rule> {
    match rule {
        Rule::Seq(elements) => {
            let mut result = vec![Rule::Blank];
            for element in elements {
                let extraction = extract_choices(element);
                let mut next_result = Vec::new();
                for entry in result {
                    for extraction_entry in extraction.iter() {
                        next_result.push(Rule::Seq(vec![entry.clone(), extraction_entry.clone()]));
                    }
                }
                result = next_result;
            }
            result
        }
        Rule::Choice(elements) => {
            let mut result = Vec::new();
            for element in elements {
                for rule in extract_choices(element) {
                    result.push(rule);
                }
            }
            result
        }
        Rule::Metadata { rule, params } => extract_choices(*rule)
            .into_iter()
            .map(|rule| Rule::Metadata {
                rule: Box::new(rule),
                params: params.clone(),
            })
            .collect(),
        _ => vec![rule],
    }
}

fn flatten_variable(variable: Variable) -> Result<SyntaxVariable> {
    let mut productions = Vec::new();
    for rule in extract_choices(variable.rule) {
        let production = RuleFlattener::new().flatten(rule);
        if !productions.contains(&production) {
            productions.push(production);
        }
    }
    Ok(SyntaxVariable {
        name: variable.name,
        kind: variable.kind,
        productions,
    })
}

fn symbol_is_used(variables: &Vec<SyntaxVariable>, symbol: Symbol) -> bool {
    for variable in variables {
        for production in &variable.productions {
            for step in &production.steps {
                if step.symbol == symbol {
                    return true;
                }
            }
        }
    }
    false
}

pub(super) fn flatten_grammar(grammar: ExtractedSyntaxGrammar) -> Result<SyntaxGrammar> {
    let mut variables = Vec::new();
    for variable in grammar.variables {
        variables.push(flatten_variable(variable)?);
    }
    for (i, variable) in variables.iter().enumerate() {
        for production in &variable.productions {
            if production.steps.is_empty() && symbol_is_used(&variables, Symbol::non_terminal(i)) {
                return Err(Error(format!(
                    "The rule `{}` matches the empty string.

Tree-sitter does not support syntactic rules that match the empty string
unless they are used only as the grammar's start rule.
",
                    variable.name
                )));
            }
        }
    }
    Ok(SyntaxGrammar {
        extra_tokens: grammar.extra_tokens,
        expected_conflicts: grammar.expected_conflicts,
        variables_to_inline: grammar.variables_to_inline,
        external_tokens: grammar.external_tokens,
        word_token: grammar.word_token,
        variables,
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::generate::grammars::VariableType;
    use crate::generate::rules::Symbol;

    #[test]
    fn test_flatten_grammar() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::seq(vec![
                Rule::non_terminal(1),
                Rule::prec_left(
                    101,
                    Rule::seq(vec![
                        Rule::non_terminal(2),
                        Rule::choice(vec![
                            Rule::prec_right(
                                102,
                                Rule::seq(vec![Rule::non_terminal(3), Rule::non_terminal(4)]),
                            ),
                            Rule::non_terminal(5),
                        ]),
                        Rule::non_terminal(6),
                    ]),
                ),
                Rule::non_terminal(7),
            ]),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![
                Production {
                    dynamic_precedence: 0,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(3))
                            .with_prec(102, Some(Associativity::Right)),
                        ProductionStep::new(Symbol::non_terminal(4))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ]
                },
                Production {
                    dynamic_precedence: 0,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(5))
                            .with_prec(101, Some(Associativity::Left)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ]
                },
            ]
        );
    }

    #[test]
    fn test_flatten_grammar_with_maximum_dynamic_precedence() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::seq(vec![
                Rule::non_terminal(1),
                Rule::prec_dynamic(
                    101,
                    Rule::seq(vec![
                        Rule::non_terminal(2),
                        Rule::choice(vec![
                            Rule::prec_dynamic(
                                102,
                                Rule::seq(vec![Rule::non_terminal(3), Rule::non_terminal(4)]),
                            ),
                            Rule::non_terminal(5),
                        ]),
                        Rule::non_terminal(6),
                    ]),
                ),
                Rule::non_terminal(7),
            ]),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![
                Production {
                    dynamic_precedence: 102,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2)),
                        ProductionStep::new(Symbol::non_terminal(3)),
                        ProductionStep::new(Symbol::non_terminal(4)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ],
                },
                Production {
                    dynamic_precedence: 101,
                    steps: vec![
                        ProductionStep::new(Symbol::non_terminal(1)),
                        ProductionStep::new(Symbol::non_terminal(2)),
                        ProductionStep::new(Symbol::non_terminal(5)),
                        ProductionStep::new(Symbol::non_terminal(6)),
                        ProductionStep::new(Symbol::non_terminal(7)),
                    ],
                },
            ]
        );
    }

    #[test]
    fn test_flatten_grammar_with_final_precedence() {
        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::prec_left(
                101,
                Rule::seq(vec![Rule::non_terminal(1), Rule::non_terminal(2)]),
            ),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![Production {
                dynamic_precedence: 0,
                steps: vec![
                    ProductionStep::new(Symbol::non_terminal(1))
                        .with_prec(101, Some(Associativity::Left)),
                    ProductionStep::new(Symbol::non_terminal(2))
                        .with_prec(101, Some(Associativity::Left)),
                ]
            }]
        );

        let result = flatten_variable(Variable {
            name: "test".to_string(),
            kind: VariableType::Named,
            rule: Rule::prec_left(101, Rule::seq(vec![Rule::non_terminal(1)])),
        })
        .unwrap();

        assert_eq!(
            result.productions,
            vec![Production {
                dynamic_precedence: 0,
                steps: vec![ProductionStep::new(Symbol::non_terminal(1))
                    .with_prec(101, Some(Associativity::Left)),]
            }]
        );
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A windowing implementation using GLFW.

use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
use windowing::RefreshWindowEvent;
use windowing::{Forward, Back};

use alert::{Alert, AlertMethods};
use extra::time::Timespec;
use extra::time;
use std::libc::c_int;
use std::local_data;
use geom::point::Point2D;
use geom::size::Size2D;
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};

use glfw;

/// A structure responsible for setting up and tearing down the entire windowing system.
pub struct Application;

impl ApplicationMethods for Application {
    fn new() -> Application {
        // Per GLFW docs it's safe to set the error callback before calling
        // glfwInit(), and this way we notice errors from init too.
        glfw::set_error_callback(~glfw::LogErrorHandler);
        glfw::init();
        Application
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        drop_local_window();
        glfw::terminate();
    }
}

macro_rules! glfw_callback(
    (
        $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr
    ) => ({
        struct GlfwCallback;
        impl $callback for GlfwCallback {
            fn call(&self $(, $arg: $arg_ty)*) {
                $block
            }
        }
        ~GlfwCallback
    });

    (
        [$($state:ident: $state_ty:ty),*],
        $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr
    ) => ({
        struct GlfwCallback {
            $($state: $state_ty,)*
        }
        impl $callback for GlfwCallback {
            fn call(&self $(, $arg: $arg_ty)*) {
                $block
            }
        }
        ~GlfwCallback {
            $($state: $state,)*
        }
    });
)

/// The type of a window.
pub struct Window {
    glfw_window: glfw::Window,

    event_queue: @mut ~[WindowEvent],

    drag_origin: Point2D<c_int>,

    mouse_down_button: @mut Option<glfw::MouseButton>,
    mouse_down_point: @mut Point2D<c_int>,

    ready_state: ReadyState,
    render_state: RenderState,

    last_title_set_time: Timespec,
}

impl WindowMethods<Application> for Window {
    /// Creates a new window.
    fn new(_: &Application) -> @mut Window {
        // Create the GLFW window.
        let glfw_window = glfw::Window::create(800, 600, "Servo", glfw::Windowed)
            .expect("Failed to create GLFW window");
        glfw_window.make_context_current();

        // Create our window object.
        let window = @mut Window {
            glfw_window: glfw_window,

            event_queue: @mut ~[],

            drag_origin: Point2D(0 as c_int, 0),

            mouse_down_button: @mut None,
            mouse_down_point: @mut Point2D(0 as c_int, 0),

            ready_state: Blank,
            render_state: IdleRenderState,

            last_title_set_time: Timespec::new(0, 0),
        };

        install_local_window(window);

        // Register event handlers.
        window.glfw_window.set_framebuffer_size_callback(
            glfw_callback!(glfw::FramebufferSizeCallback(_win: &glfw::Window, width: i32, height: i32) {
                local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint));
            }));
        window.glfw_window.set_refresh_callback(
            glfw_callback!(glfw::WindowRefreshCallback(_win: &glfw::Window) {
                local_window().event_queue.push(RefreshWindowEvent);
            }));
        window.glfw_window.set_key_callback(
            glfw_callback!(glfw::KeyCallback(_win: &glfw::Window, key: glfw::Key, _scancode: c_int,
                                             action: glfw::Action, mods: glfw::Modifiers) {
                if action == glfw::Press {
                    local_window().handle_key(key, mods)
                }
            }));
        window.glfw_window.set_mouse_button_callback(
            glfw_callback!(glfw::MouseButtonCallback(win: &glfw::Window, button: glfw::MouseButton,
                                                     action: glfw::Action, _mods: glfw::Modifiers) {
                let (x, y) = win.get_cursor_pos();
                //handle hidpi displays, since GLFW returns non-hi-def coordinates.
                let (backing_size, _) = win.get_framebuffer_size();
                let (window_size, _) = win.get_size();
                let hidpi = (backing_size as f32) / (window_size as f32);
                let x = x as f32 * hidpi;
                let y = y as f32 * hidpi;
                if button == glfw::MouseButtonLeft || button == glfw::MouseButtonRight {
                    local_window().handle_mouse(button, action, x as i32, y as i32);
                }
            }));
        window.glfw_window.set_scroll_callback(
            glfw_callback!(glfw::ScrollCallback(win: &glfw::Window, xpos: f64, ypos: f64) {
                let dx = (xpos as f32) * 30.0;
                let dy = (ypos as f32) * 30.0;

                let (x, y) = win.get_cursor_pos();
                //handle hidpi displays, since GLFW returns non-hi-def coordinates.
                let (backing_size, _) = win.get_framebuffer_size();
                let (window_size, _) = win.get_size();
                let hidpi = (backing_size as f32) / (window_size as f32);
                let x = x as f32 * hidpi;
                let y = y as f32 * hidpi;

                local_window().event_queue.push(ScrollWindowEvent(Point2D(dx, dy), Point2D(x as i32, y as i32)));
            }));

        window
    }

    /// Returns the size of the window.
    fn size(&self) -> Size2D<f32> {
        let (width, height) = self.glfw_window.get_framebuffer_size();
        Size2D(width as f32, height as f32)
    }

    /// Presents the window to the screen (perhaps by page flipping).
    fn present(&mut self) {
        self.glfw_window.swap_buffers();
    }

    fn recv(@mut self) -> WindowEvent {
        if !self.event_queue.is_empty() {
            return self.event_queue.shift()
        }
        glfw::poll_events();

        if self.glfw_window.should_close() {
            QuitWindowEvent
        } else if !self.event_queue.is_empty() {
            self.event_queue.shift()
        } else {
            IdleWindowEvent
        }
    }

    /// Sets the ready state.
    fn set_ready_state(@mut self, ready_state: ReadyState) {
        self.ready_state = ready_state;
        self.update_window_title()
    }

    /// Sets the render state.
    fn set_render_state(@mut self, render_state: RenderState) {
        if self.ready_state == FinishedLoading &&
            self.render_state == RenderingRenderState &&
            render_state == IdleRenderState {
            // page loaded
            self.event_queue.push(FinishedWindowEvent);
        }

        self.render_state = render_state;
        self.update_window_title()
    }

    fn hidpi_factor(@mut self) -> f32 {
        let (backing_size, _) = self.glfw_window.get_framebuffer_size();
        let (window_size, _) = self.glfw_window.get_size();
        (backing_size as f32) / (window_size as f32)
    }
}

impl Window {
    /// Helper function to set the window title in accordance with the ready state.
    fn update_window_title(&mut self) {
        let now = time::get_time();
        if now.sec == self.last_title_set_time.sec {
            return
        }
        self.last_title_set_time = now;

        match self.ready_state {
            Blank => {
                self.glfw_window.set_title("blank — Servo")
            }
            Loading => {
                self.glfw_window.set_title("Loading — Servo")
            }
            PerformingLayout => {
                self.glfw_window.set_title("Performing Layout — Servo")
            }
            FinishedLoading => {
                match self.render_state {
                    RenderingRenderState => {
                        self.glfw_window.set_title("Rendering — Servo")
                    }
                    IdleRenderState => {
                        self.glfw_window.set_title("Servo")
                    }
                }
            }
        }
    }

    /// Helper function to handle keyboard events.
    fn handle_key(&self, key: glfw::Key, mods: glfw::Modifiers) {
        match key {
            glfw::KeyEscape => self.glfw_window.set_should_close(true),
            glfw::KeyL if mods.contains(glfw::Control) => self.load_url(), // Ctrl+L
            glfw::KeyEqual if mods.contains(glfw::Control) => { // Ctrl-+
                self.event_queue.push(ZoomWindowEvent(1.1));
            }
            glfw::KeyMinus if mods.contains(glfw::Control) => { // Ctrl--
                self.event_queue.push(ZoomWindowEvent(0.90909090909));
            }
            glfw::KeyBackspace if mods.contains(glfw::Shift) => { // Shift-Backspace
                self.event_queue.push(NavigationWindowEvent(Forward));
            }
            glfw::KeyBackspace => { // Backspace
                self.event_queue.push(NavigationWindowEvent(Back));
            }
            _ => {}
        }
    }

    /// Helper function to handle a click
    fn handle_mouse(&self, button: glfw::MouseButton, action: glfw::Action, x: c_int, y: c_int) {
        // FIXME(tkuehn): max pixel dist should be based on pixel density
        let max_pixel_dist = 10f64;
        let event = match action {
            glfw::Press => {
                *self.mouse_down_point = Point2D(x, y);
                *self.mouse_down_button = Some(button);
                MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
            }
            glfw::Release => {
                match *self.mouse_down_button {
                    None => (),
                    Some(but) if button == but => {
                        let pixel_dist = *self.mouse_down_point - Point2D(x, y);
                        let pixel_dist = ((pixel_dist.x * pixel_dist.x +
                                           pixel_dist.y * pixel_dist.y) as f64).sqrt();
                        if pixel_dist < max_pixel_dist {
                            let click_event = MouseWindowClickEvent(button as uint,
                                                                    Point2D(x as f32, y as f32));
                            self.event_queue.push(MouseWindowEventClass(click_event));
                        }
                    }
                    Some(_) => (),
                }
                MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
            }
            _ => fail!("I cannot recognize the type of mouse action that occured. :-(")
        };
        self.event_queue.push(MouseWindowEventClass(event));
    }

    /// Helper function to pop up an alert box prompting the user to load a URL.
    fn load_url(&self) {
        let mut alert: Alert = AlertMethods::new("Navigate to:");
        alert.add_prompt();
        alert.run();
        let value = alert.prompt_value();
        if "" == value {    // To avoid crashing on Linux.
            self.event_queue.push(LoadUrlWindowEvent(~"http://purple.com/"))
        } else {
            self.event_queue.push(LoadUrlWindowEvent(value))
        }
    }
}

static TLS_KEY: local_data::Key<@mut Window> = &local_data::Key;

fn install_local_window(window: @mut Window) {
    local_data::set(TLS_KEY, window);
}

fn drop_local_window() {
    local_data::pop(TLS_KEY);
}

fn local_window() -> @mut Window {
    local_data::get(TLS_KEY, |v| *v.unwrap())
}
<commit_msg>auto merge of #1502 : cmr/servo/handle_init_error, r=pcwalton<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A windowing implementation using GLFW.

use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
use windowing::RefreshWindowEvent;
use windowing::{Forward, Back};

use alert::{Alert, AlertMethods};
use extra::time::Timespec;
use extra::time;
use std::libc::{exit, c_int};
use std::local_data;
use geom::point::Point2D;
use geom::size::Size2D;
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};

use glfw;

/// A structure responsible for setting up and tearing down the entire windowing system.
pub struct Application;

impl ApplicationMethods for Application {
    fn new() -> Application {
        // Per GLFW docs it's safe to set the error callback before calling
        // glfwInit(), and this way we notice errors from init too.
        glfw::set_error_callback(~glfw::LogErrorHandler);

        if glfw::init().is_err() {
            // handles things like inability to connect to X
            // cannot simply fail, since the runtime isn't up yet (causes a nasty abort)
            println!("GLFW initialization failed");
            unsafe { exit(1); }
        }

        Application
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        drop_local_window();
        glfw::terminate();
    }
}

macro_rules! glfw_callback(
    (
        $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr
    ) => ({
        struct GlfwCallback;
        impl $callback for GlfwCallback {
            fn call(&self $(, $arg: $arg_ty)*) {
                $block
            }
        }
        ~GlfwCallback
    });

    (
        [$($state:ident: $state_ty:ty),*],
        $callback:path ($($arg:ident: $arg_ty:ty),*) $block:expr
    ) => ({
        struct GlfwCallback {
            $($state: $state_ty,)*
        }
        impl $callback for GlfwCallback {
            fn call(&self $(, $arg: $arg_ty)*) {
                $block
            }
        }
        ~GlfwCallback {
            $($state: $state,)*
        }
    });
)

/// The type of a window.
pub struct Window {
    glfw_window: glfw::Window,

    event_queue: @mut ~[WindowEvent],

    drag_origin: Point2D<c_int>,

    mouse_down_button: @mut Option<glfw::MouseButton>,
    mouse_down_point: @mut Point2D<c_int>,

    ready_state: ReadyState,
    render_state: RenderState,

    last_title_set_time: Timespec,
}

impl WindowMethods<Application> for Window {
    /// Creates a new window.
    fn new(_: &Application) -> @mut Window {
        // Create the GLFW window.
        let glfw_window = glfw::Window::create(800, 600, "Servo", glfw::Windowed)
            .expect("Failed to create GLFW window");
        glfw_window.make_context_current();

        // Create our window object.
        let window = @mut Window {
            glfw_window: glfw_window,

            event_queue: @mut ~[],

            drag_origin: Point2D(0 as c_int, 0),

            mouse_down_button: @mut None,
            mouse_down_point: @mut Point2D(0 as c_int, 0),

            ready_state: Blank,
            render_state: IdleRenderState,

            last_title_set_time: Timespec::new(0, 0),
        };

        install_local_window(window);

        // Register event handlers.
        window.glfw_window.set_framebuffer_size_callback(
            glfw_callback!(glfw::FramebufferSizeCallback(_win: &glfw::Window, width: i32, height: i32) {
                local_window().event_queue.push(ResizeWindowEvent(width as uint, height as uint));
            }));
        window.glfw_window.set_refresh_callback(
            glfw_callback!(glfw::WindowRefreshCallback(_win: &glfw::Window) {
                local_window().event_queue.push(RefreshWindowEvent);
            }));
        window.glfw_window.set_key_callback(
            glfw_callback!(glfw::KeyCallback(_win: &glfw::Window, key: glfw::Key, _scancode: c_int,
                                             action: glfw::Action, mods: glfw::Modifiers) {
                if action == glfw::Press {
                    local_window().handle_key(key, mods)
                }
            }));
        window.glfw_window.set_mouse_button_callback(
            glfw_callback!(glfw::MouseButtonCallback(win: &glfw::Window, button: glfw::MouseButton,
                                                     action: glfw::Action, _mods: glfw::Modifiers) {
                let (x, y) = win.get_cursor_pos();
                //handle hidpi displays, since GLFW returns non-hi-def coordinates.
                let (backing_size, _) = win.get_framebuffer_size();
                let (window_size, _) = win.get_size();
                let hidpi = (backing_size as f32) / (window_size as f32);
                let x = x as f32 * hidpi;
                let y = y as f32 * hidpi;
                if button == glfw::MouseButtonLeft || button == glfw::MouseButtonRight {
                    local_window().handle_mouse(button, action, x as i32, y as i32);
                }
            }));
        window.glfw_window.set_scroll_callback(
            glfw_callback!(glfw::ScrollCallback(win: &glfw::Window, xpos: f64, ypos: f64) {
                let dx = (xpos as f32) * 30.0;
                let dy = (ypos as f32) * 30.0;

                let (x, y) = win.get_cursor_pos();
                //handle hidpi displays, since GLFW returns non-hi-def coordinates.
                let (backing_size, _) = win.get_framebuffer_size();
                let (window_size, _) = win.get_size();
                let hidpi = (backing_size as f32) / (window_size as f32);
                let x = x as f32 * hidpi;
                let y = y as f32 * hidpi;

                local_window().event_queue.push(ScrollWindowEvent(Point2D(dx, dy), Point2D(x as i32, y as i32)));
            }));

        window
    }

    /// Returns the size of the window.
    fn size(&self) -> Size2D<f32> {
        let (width, height) = self.glfw_window.get_framebuffer_size();
        Size2D(width as f32, height as f32)
    }

    /// Presents the window to the screen (perhaps by page flipping).
    fn present(&mut self) {
        self.glfw_window.swap_buffers();
    }

    fn recv(@mut self) -> WindowEvent {
        if !self.event_queue.is_empty() {
            return self.event_queue.shift()
        }
        glfw::poll_events();

        if self.glfw_window.should_close() {
            QuitWindowEvent
        } else if !self.event_queue.is_empty() {
            self.event_queue.shift()
        } else {
            IdleWindowEvent
        }
    }

    /// Sets the ready state.
    fn set_ready_state(@mut self, ready_state: ReadyState) {
        self.ready_state = ready_state;
        self.update_window_title()
    }

    /// Sets the render state.
    fn set_render_state(@mut self, render_state: RenderState) {
        if self.ready_state == FinishedLoading &&
            self.render_state == RenderingRenderState &&
            render_state == IdleRenderState {
            // page loaded
            self.event_queue.push(FinishedWindowEvent);
        }

        self.render_state = render_state;
        self.update_window_title()
    }

    fn hidpi_factor(@mut self) -> f32 {
        let (backing_size, _) = self.glfw_window.get_framebuffer_size();
        let (window_size, _) = self.glfw_window.get_size();
        (backing_size as f32) / (window_size as f32)
    }
}

impl Window {
    /// Helper function to set the window title in accordance with the ready state.
    fn update_window_title(&mut self) {
        let now = time::get_time();
        if now.sec == self.last_title_set_time.sec {
            return
        }
        self.last_title_set_time = now;

        match self.ready_state {
            Blank => {
                self.glfw_window.set_title("blank — Servo")
            }
            Loading => {
                self.glfw_window.set_title("Loading — Servo")
            }
            PerformingLayout => {
                self.glfw_window.set_title("Performing Layout — Servo")
            }
            FinishedLoading => {
                match self.render_state {
                    RenderingRenderState => {
                        self.glfw_window.set_title("Rendering — Servo")
                    }
                    IdleRenderState => {
                        self.glfw_window.set_title("Servo")
                    }
                }
            }
        }
    }

    /// Helper function to handle keyboard events.
    fn handle_key(&self, key: glfw::Key, mods: glfw::Modifiers) {
        match key {
            glfw::KeyEscape => self.glfw_window.set_should_close(true),
            glfw::KeyL if mods.contains(glfw::Control) => self.load_url(), // Ctrl+L
            glfw::KeyEqual if mods.contains(glfw::Control) => { // Ctrl-+
                self.event_queue.push(ZoomWindowEvent(1.1));
            }
            glfw::KeyMinus if mods.contains(glfw::Control) => { // Ctrl--
                self.event_queue.push(ZoomWindowEvent(0.90909090909));
            }
            glfw::KeyBackspace if mods.contains(glfw::Shift) => { // Shift-Backspace
                self.event_queue.push(NavigationWindowEvent(Forward));
            }
            glfw::KeyBackspace => { // Backspace
                self.event_queue.push(NavigationWindowEvent(Back));
            }
            _ => {}
        }
    }

    /// Helper function to handle a click
    fn handle_mouse(&self, button: glfw::MouseButton, action: glfw::Action, x: c_int, y: c_int) {
        // FIXME(tkuehn): max pixel dist should be based on pixel density
        let max_pixel_dist = 10f64;
        let event = match action {
            glfw::Press => {
                *self.mouse_down_point = Point2D(x, y);
                *self.mouse_down_button = Some(button);
                MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
            }
            glfw::Release => {
                match *self.mouse_down_button {
                    None => (),
                    Some(but) if button == but => {
                        let pixel_dist = *self.mouse_down_point - Point2D(x, y);
                        let pixel_dist = ((pixel_dist.x * pixel_dist.x +
                                           pixel_dist.y * pixel_dist.y) as f64).sqrt();
                        if pixel_dist < max_pixel_dist {
                            let click_event = MouseWindowClickEvent(button as uint,
                                                                    Point2D(x as f32, y as f32));
                            self.event_queue.push(MouseWindowEventClass(click_event));
                        }
                    }
                    Some(_) => (),
                }
                MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
            }
            _ => fail!("I cannot recognize the type of mouse action that occured. :-(")
        };
        self.event_queue.push(MouseWindowEventClass(event));
    }

    /// Helper function to pop up an alert box prompting the user to load a URL.
    fn load_url(&self) {
        let mut alert: Alert = AlertMethods::new("Navigate to:");
        alert.add_prompt();
        alert.run();
        let value = alert.prompt_value();
        if "" == value {    // To avoid crashing on Linux.
            self.event_queue.push(LoadUrlWindowEvent(~"http://purple.com/"))
        } else {
            self.event_queue.push(LoadUrlWindowEvent(value))
        }
    }
}

static TLS_KEY: local_data::Key<@mut Window> = &local_data::Key;

fn install_local_window(window: @mut Window) {
    local_data::set(TLS_KEY, window);
}

fn drop_local_window() {
    local_data::pop(TLS_KEY);
}

fn local_window() -> @mut Window {
    local_data::get(TLS_KEY, |v| *v.unwrap())
}
<|endoftext|>


<commit_before>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn add_transition(&mut self, id0: int, c: char, id1: int)
	{
		self.states[id0].add_transition(c, id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}
	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t, id) = (self.states[curr[i]].transitions[j]).clone();
					if t == c
					{
						next.push(id);
					}
					else if t == '%'
					{
						curr.push(id);
						l += 1;
					}
				}
				i += 1;
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else // the NFA has eaten all of the characters
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t , id) = (self.states[curr[i]].transitions[j]).clone();
					if t == '%'
					{
						next.push(id);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone, Eq)]
struct State
{
	accept: bool,
	transitions: ~[(char, int)]
}

impl State
{
	pub fn new(b: bool)	->	State
	{
		State { accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("matching=%? transitions={", self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, c: char, id: int )
	{
		self.transitions.push((c, id));
	}
}

fn main()
{
	let test = std::os::args()[1];
	let lang = ['a', 'b'];
	let strings = ~[~"", ~"a", ~"b", ~"aa", ~"bb", ~"ab", ~"ba", ~"aab", ~"aba", ~"baa", ~"abb", ~"bab", ~"bba", ~"bbb", ~"aaa", ~"abbb", ~"abba"];
	let mut nfa = NFA::new();
	//let mut parenthesis: ~[int] = ~[];
	//let head_state = State::new(false);
	//nfa.add_state(head_state);
	let mut j = -1;
	let mut escaped = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		if c == '\\'
		{
			escaped = true;
		}
		/*
		else if c == '(' && !escaped
		{
			// note the place and make an 'in' state
			parenthesis.push(i);
			let state_in = State::new('%', false);
			nfa.add_state(state_in);
			j += 1;

			// link this and the previous
			nfa.link_states(j-1, j);
		}
		else if c == ')' && !escaped
		{
			let state_out = State::new('%', false);
			nfa.add_state(state_out);
			j += 1;

			// link to state_in
			nfa.link_states(j, parenthesis.pop()-1);

			// link to prev
			nfa.link_states(j-1, j);
		}
		*/
		else if c == '*' && !escaped
		{
			// link curr to itself
			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, j);
				}
			}
			// add epsilon transition to skip this state
			nfa.add_transition(j, '%', j+1);

		}
		else if c == '+' && !escaped
		{
			let state_next = State::new(false);
			// link next to curr

			nfa.add_state(state_next);
			j += 1;

			// link next to curr
			nfa.add_transition(j, '%', j-1);
			// add transition to next state
			nfa.add_transition(j, '%', j+1);
		}
		else if c == '?' && !escaped
		{
			// add epsilon transition
			nfa.add_transition(j, '%', j+1);
		}
		else if c == '.' && !escaped
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// unconditional jump
			for i in range(0, lang.len())
			{
				nfa.add_transition(j, lang[i], j+1);
			}
		}
		else
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// link with next
			nfa.add_transition(j, c, j+1);
			escaped = false;
		}

		nfa.print();
	}
	// make the last state true
	let state = State::new(true);
	nfa.add_state(state);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}

}
<commit_msg>added helper function to make test strings:<commit_after>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn add_transition(&mut self, id0: int, c: char, id1: int)
	{
		self.states[id0].add_transition(c, id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}
	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t, id) = (self.states[curr[i]].transitions[j]).clone();
					if t == c
					{
						next.push(id);
					}
					else if t == '%'
					{
						curr.push(id);
						l += 1;
					}
				}
				i += 1;
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else // the NFA has eaten all of the characters
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				for j in range(0, self.states[curr[i]].transitions.len())
				{
					let (t , id) = (self.states[curr[i]].transitions[j]).clone();
					if t == '%'
					{
						next.push(id);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone, Eq)]
struct State
{
	accept: bool,
	transitions: ~[(char, int)]
}

impl State
{
	pub fn new(b: bool)	->	State
	{
		State { accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("matching=%? transitions={", self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, c: char, id: int )
	{
		self.transitions.push((c, id));
	}
}

fn generate(lang: &[char], len: uint)	->	~[~str]
{
	let mut set = ~[];
	if len == 0 { return ~[~""]; }
	if len == 1
	{
		for i in range(0, lang.len())
		{
			set.push(lang[i].to_str());
		}
		return set;
	}
	for i in range(0, lang.len())
	{
		let s = generate(lang, len-1);
		for j in range(0, s.len())
		{
			set.push(lang[i].to_str() + s[j].clone());
		}
	}
	return set;
}

fn main()
{
	let test = std::os::args()[1];
	let lang = ['a', 'b'];
	let len = 4u;
	let mut strings = ~[];
	for i in range(0, len+1)
	{
		let s = generate(lang, i);
		for j in range(0,s.len())
		{
			strings.push(s[j].clone());
		}
	}
	let mut nfa = NFA::new();
	//let mut parenthesis: ~[int] = ~[];
	//let head_state = State::new(false);
	//nfa.add_state(head_state);
	let mut j = -1;
	let mut escaped = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		if c == '\\'
		{
			escaped = true;
		}
		/*
		else if c == '(' && !escaped
		{
			// note the place and make an 'in' state
			parenthesis.push(i);
			let state_in = State::new('%', false);
			nfa.add_state(state_in);
			j += 1;

			// link this and the previous
			nfa.link_states(j-1, j);
		}
		else if c == ')' && !escaped
		{
			let state_out = State::new('%', false);
			nfa.add_state(state_out);
			j += 1;

			// link to state_in
			nfa.link_states(j, parenthesis.pop()-1);

			// link to prev
			nfa.link_states(j-1, j);
		}
		*/
		else if c == '*' && !escaped
		{
			// link curr to itself
			for i in range(0, nfa.states[j].transitions.len())
			{
				let (a,_) = (nfa.states[j].transitions[i]).clone();
				if a != '%'
				{
					nfa.add_transition(j, a, j);
				}
			}
			// add epsilon transition to skip this state
			nfa.add_transition(j, '%', j+1);

		}
		else if c == '+' && !escaped
		{
			let state_next = State::new(false);
			// link next to curr

			nfa.add_state(state_next);
			j += 1;

			// link next to curr
			nfa.add_transition(j, '%', j-1);
			// add transition to next state
			nfa.add_transition(j, '%', j+1);
		}
		else if c == '?' && !escaped
		{
			// add epsilon transition
			nfa.add_transition(j, '%', j+1);
		}
		else if c == '.' && !escaped
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// unconditional jump
			for i in range(0, lang.len())
			{
				nfa.add_transition(j, lang[i], j+1);
			}
		}
		else
		{
			let state = State::new(false);
			nfa.add_state(state);
			j += 1;

			// link with next
			nfa.add_transition(j, c, j+1);
			escaped = false;
		}

		nfa.print();
	}
	// make the last state true
	let state = State::new(true);
	nfa.add_state(state);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}

}
<|endoftext|>


<commit_before>//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::{
    fmt::{self, Display, Formatter},
    string::String,
};

use log::{error, info};

use oak_abi::OakStatus;
use std::thread::{self, JoinHandle};

use crate::{
    pretty_name_for_thread,
    runtime::{Handle, RuntimeProxy},
};
use oak_abi::proto::oak::log::{Level, LogMessage};
use prost::Message;

pub struct LogNode {
    config_name: String,
    runtime: RuntimeProxy,
    reader: Handle,
}

impl LogNode {
    /// Creates a new [`LogNode`] instance, but does not start it.
    pub fn new(config_name: &str, runtime: RuntimeProxy, reader: Handle) -> Self {
        Self {
            config_name: config_name.to_string(),
            runtime,
            reader,
        }
    }

    /// Main node worker thread.
    fn worker_thread(self) {
        let pretty_name = pretty_name_for_thread(&thread::current());
        let result = self.logger_loop(&pretty_name);
        info!("{} LOG: exiting log thread {:?}", pretty_name, result);
        self.runtime.exit_node();
    }

    fn logger_loop(&self, pretty_name: &str) -> Result<(), OakStatus> {
        loop {
            // An error indicates the Runtime is terminating. We ignore it here and keep trying to
            // read in case a Wasm Node wants to emit remaining messages. We will return
            // once the channel is closed.

            let _ = self.runtime.wait_on_channels(&[Some(self.reader)]);

            if let Some(message) = self.runtime.channel_read(self.reader)? {
                match LogMessage::decode(&*message.data) {
                    Ok(msg) => info!(
                        "{} LOG: {} {}:{}: {}",
                        pretty_name,
                        to_level_name(msg.level),
                        msg.file,
                        msg.line,
                        msg.message
                    ),
                    Err(error) => error!("{} Could not parse LogMessage: {}", pretty_name, error),
                }
            }
        }
    }
}

impl Display for LogNode {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "LogNode({})", self.config_name)
    }
}

impl super::Node for LogNode {
    fn start(self: Box<Self>) -> Result<JoinHandle<()>, OakStatus> {
        let thread_handle = thread::Builder::new()
            .name(self.to_string())
            .spawn(move || self.worker_thread())
            .expect("failed to spawn thread");
        Ok(thread_handle)
    }
}

fn to_level_name(level: i32) -> String {
    format!(
        "{:?}",
        Level::from_i32(level).unwrap_or(Level::UnknownLevel)
    )
    .to_ascii_uppercase()
}
<commit_msg>runtime/rust: pass file/line/level through to log<commit_after>//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::{
    fmt::{self, Display, Formatter},
    string::String,
};

use log::{error, info, log};

use oak_abi::OakStatus;
use std::thread::{self, JoinHandle};

use crate::{
    pretty_name_for_thread,
    runtime::{Handle, RuntimeProxy},
};
use oak_abi::proto::oak::log::{Level, LogMessage};
use prost::Message;

pub struct LogNode {
    config_name: String,
    runtime: RuntimeProxy,
    reader: Handle,
}

impl LogNode {
    /// Creates a new [`LogNode`] instance, but does not start it.
    pub fn new(config_name: &str, runtime: RuntimeProxy, reader: Handle) -> Self {
        Self {
            config_name: config_name.to_string(),
            runtime,
            reader,
        }
    }

    /// Main node worker thread.
    fn worker_thread(self) {
        let pretty_name = pretty_name_for_thread(&thread::current());
        let result = self.logger_loop(&pretty_name);
        info!("{} LOG: exiting log thread {:?}", pretty_name, result);
        self.runtime.exit_node();
    }

    fn logger_loop(&self, pretty_name: &str) -> Result<(), OakStatus> {
        loop {
            // An error indicates the Runtime is terminating. We ignore it here and keep trying to
            // read in case a Wasm Node wants to emit remaining messages. We will return
            // once the channel is closed.
            let _ = self.runtime.wait_on_channels(&[Some(self.reader)]);

            if let Some(message) = self.runtime.channel_read(self.reader)? {
                match LogMessage::decode(&*message.data) {
                    Ok(msg) => log!(
                        target: &format!("{}:{}", msg.file, msg.line),
                        to_level(msg.level),
                        "{}",
                        msg.message,
                    ),
                    Err(error) => error!("{} Could not parse LogMessage: {}", pretty_name, error),
                }
            }
        }
    }
}

impl Display for LogNode {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "LogNode({})", self.config_name)
    }
}

impl super::Node for LogNode {
    fn start(self: Box<Self>) -> Result<JoinHandle<()>, OakStatus> {
        let thread_handle = thread::Builder::new()
            .name(self.to_string())
            .spawn(move || self.worker_thread())
            .expect("failed to spawn thread");
        Ok(thread_handle)
    }
}

fn to_level(level: i32) -> log::Level {
    match Level::from_i32(level).unwrap_or(Level::UnknownLevel) {
        Level::UnknownLevel => log::Level::Error,
        Level::Error => log::Level::Error,
        Level::Warn => log::Level::Warn,
        Level::Info => log::Level::Info,
        Level::Debugging => log::Level::Debug,
        Level::Trace => log::Level::Trace,
    }
}
<|endoftext|>


<commit_before>use std::process;
use std::process::Command;
use std::{env, fs};

fn main() {
    let usage = r#"tutorial-maker <username> <program-name> <language> <program-type>

    <language> can only be the following:

    - rust

    <program-type> can only be the following:

    - library
"#;
    let args: Vec<String> = env::args().collect();

    if args.len() < 5 {
        println!("{usage}");

        process::exit(1);
    }

    println!("{:?}", args);

    let username = args[1].to_lowercase();
    let program_name = args[2].to_lowercase();
    let args3 = args[3].to_lowercase();
    let language = if args3 == "rust" {
        "rust"
    } else {
        println!("{usage}");

        process::exit(1);
    };

    let args4 = args[4].to_lowercase();
    let program_type = if args4 == "library" {
        "library"
    } else {
        println!("{usage}");

        process::exit(1);
    };

    let path_name = format!("repos/github/{username}");

    println!("mkdir -p path_name: {path_name}");

    fs::create_dir_all(&path_name).expect("unable to create path name");

    println!("cd {path_name}");

    env::set_current_dir(&path_name).expect("changing directory failed");

    let app_name = format!("{program_name}-{program_type}");
    let folder_name = format!("{program_name}-{language}-{program_type}");
    let repo_name = format!("{username}/{folder_name}");

    println!("rm -rf {folder_name}");

    let removing_folder_output = Command::new("rm")
        .arg("-rf")
        .arg(&folder_name)
        .output()
        .expect("removing folder failed");

    if removing_folder_output.status.success() {
        println!(
            "cloning stdout: {}",
            String::from_utf8_lossy(&removing_folder_output.stdout)
        );
    } else {
        println!(
            "cloning stderr: {}",
            String::from_utf8_lossy(&removing_folder_output.stderr)
        );

        process::exit(1);
    }

    println!("gh repo clone {repo_name}");

    let cloning_output = Command::new("gh")
        .arg("repo")
        .arg("clone")
        .arg(&repo_name)
        .output()
        .expect("cloning failed");

    if cloning_output.status.success() {
        println!(
            "cloning stdout: {}",
            String::from_utf8_lossy(&cloning_output.stdout)
        );
    } else {
        println!(
            "cloning stderr: {}",
            String::from_utf8_lossy(&cloning_output.stderr)
        );

        process::exit(1);
    }

    println!("cd {folder_name}");

    env::set_current_dir(&folder_name).expect("changing directory failed");

    println!("git rev-list --all --reverse");

    let git_rev_list_output = Command::new("git")
        .arg("rev-list")
        .arg("--all")
        .arg("--reverse")
        .output()
        .expect("rev-list failed");

    if git_rev_list_output.status.success() {
        let git_rev_list_output_cow =
            String::from_utf8_lossy(&git_rev_list_output.stdout).to_string();

        for (i, commit_hash) in git_rev_list_output_cow.split("\n").enumerate() {
            println!("i: {i}");
            if !commit_hash.is_empty() {
                println!("git checkout {commit_hash}");

                let git_checkout_output = Command::new("git")
                    .arg("checkout")
                    .arg(commit_hash)
                    .output()
                    .expect("checkout failed");

                if git_checkout_output.status.success() {
                    println!(
                        "git checkout stdout: {}",
                        String::from_utf8(git_checkout_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "git checkout stderr: {}",
                        String::from_utf8(git_checkout_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                println!("git show");

                let git_show_output = Command::new("git")
                    .arg("show")
                    .output()
                    .expect("show failed");

                if git_show_output.status.success() {
                    println!(
                        "git show stdout: {}",
                        String::from_utf8(git_show_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "git show stderr: {}",
                        String::from_utf8(git_show_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                let parent_path = env::current_dir().expect("getting current directory failed");
                let mut path = parent_path.clone();
                path.push(&app_name);
                let metadata = fs::metadata(path);
                match metadata {
                    Ok(_) => {
                        println!("{app_name} found");
                    }
                    Err(_) => {
                        println!("{app_name} not found");
                        continue;
                    }
                };

                println!("cd {app_name}");

                env::set_current_dir(&app_name).expect("changing directory failed");

                println!("cargo test");

                let cargo_test_output = Command::new("cargo")
                    .arg("test")
                    .output()
                    .expect("test failed");

                if cargo_test_output.status.success() {
                    println!(
                        "cargo test stdout: {}",
                        String::from_utf8(cargo_test_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "cargo test stderr: {}",
                        String::from_utf8(cargo_test_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                println!("cd ..");

                env::set_current_dir(parent_path).expect("changing directory failed");
            }
        }

        println!(
            "rev-list stdout: {}",
            String::from_utf8(git_rev_list_output.stdout).unwrap()
        );
    } else {
        println!(
            "rev-list stderr: {}",
            String::from_utf8(git_rev_list_output.stderr).unwrap()
        );

        process::exit(1);
    }
}
<commit_msg>displaying git hashes at the beginning<commit_after>use std::process;
use std::process::Command;
use std::{env, fs};

fn main() {
    let usage = r#"tutorial-maker <username> <program-name> <language> <program-type>

    <language> can only be the following:

    - rust

    <program-type> can only be the following:

    - library
"#;
    let args: Vec<String> = env::args().collect();

    if args.len() < 5 {
        println!("{usage}");

        process::exit(1);
    }

    println!("{:?}", args);

    let username = args[1].to_lowercase();
    let program_name = args[2].to_lowercase();
    let args3 = args[3].to_lowercase();
    let language = if args3 == "rust" {
        "rust"
    } else {
        println!("{usage}");

        process::exit(1);
    };

    let args4 = args[4].to_lowercase();
    let program_type = if args4 == "library" {
        "library"
    } else {
        println!("{usage}");

        process::exit(1);
    };

    let path_name = format!("repos/github/{username}");

    println!("mkdir -p path_name: {path_name}");

    fs::create_dir_all(&path_name).expect("unable to create path name");

    println!("cd {path_name}");

    env::set_current_dir(&path_name).expect("changing directory failed");

    let app_name = format!("{program_name}-{program_type}");
    let folder_name = format!("{program_name}-{language}-{program_type}");
    let repo_name = format!("{username}/{folder_name}");

    println!("rm -rf {folder_name}");

    let removing_folder_output = Command::new("rm")
        .arg("-rf")
        .arg(&folder_name)
        .output()
        .expect("removing folder failed");

    if removing_folder_output.status.success() {
        println!(
            "cloning stdout: {}",
            String::from_utf8_lossy(&removing_folder_output.stdout)
        );
    } else {
        println!(
            "cloning stderr: {}",
            String::from_utf8_lossy(&removing_folder_output.stderr)
        );

        process::exit(1);
    }

    println!("gh repo clone {repo_name}");

    let cloning_output = Command::new("gh")
        .arg("repo")
        .arg("clone")
        .arg(&repo_name)
        .output()
        .expect("cloning failed");

    if cloning_output.status.success() {
        println!(
            "cloning stdout: {}",
            String::from_utf8_lossy(&cloning_output.stdout)
        );
    } else {
        println!(
            "cloning stderr: {}",
            String::from_utf8_lossy(&cloning_output.stderr)
        );

        process::exit(1);
    }

    println!("cd {folder_name}");

    env::set_current_dir(&folder_name).expect("changing directory failed");

    println!("git rev-list --all --reverse");

    let git_rev_list_output = Command::new("git")
        .arg("rev-list")
        .arg("--all")
        .arg("--reverse")
        .output()
        .expect("rev-list failed");

    println!(
        "rev-list stdout: {}",
        String::from_utf8(git_rev_list_output.stdout.clone()).unwrap()
    );

    if git_rev_list_output.status.success() {
        let git_rev_list_output_cow =
            String::from_utf8_lossy(&git_rev_list_output.stdout).to_string();

        for (i, commit_hash) in git_rev_list_output_cow.split("\n").enumerate() {
            println!("i: {i}");
            if !commit_hash.is_empty() {
                println!("git checkout {commit_hash}");

                let git_checkout_output = Command::new("git")
                    .arg("checkout")
                    .arg(commit_hash)
                    .output()
                    .expect("checkout failed");

                if git_checkout_output.status.success() {
                    println!(
                        "git checkout stdout: {}",
                        String::from_utf8(git_checkout_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "git checkout stderr: {}",
                        String::from_utf8(git_checkout_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                println!("git show");

                let git_show_output = Command::new("git")
                    .arg("show")
                    .output()
                    .expect("show failed");

                if git_show_output.status.success() {
                    println!(
                        "git show stdout: {}",
                        String::from_utf8(git_show_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "git show stderr: {}",
                        String::from_utf8(git_show_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                let parent_path = env::current_dir().expect("getting current directory failed");
                let mut path = parent_path.clone();
                path.push(&app_name);
                let metadata = fs::metadata(path);
                match metadata {
                    Ok(_) => {
                        println!("{app_name} found");
                    }
                    Err(_) => {
                        println!("{app_name} not found");
                        continue;
                    }
                };

                println!("cd {app_name}");

                env::set_current_dir(&app_name).expect("changing directory failed");

                println!("cargo test");

                let cargo_test_output = Command::new("cargo")
                    .arg("test")
                    .output()
                    .expect("test failed");

                if cargo_test_output.status.success() {
                    println!(
                        "cargo test stdout: {}",
                        String::from_utf8(cargo_test_output.stdout).unwrap()
                    );
                } else {
                    println!(
                        "cargo test stderr: {}",
                        String::from_utf8(cargo_test_output.stderr).unwrap()
                    );

                    process::exit(1);
                }

                println!("cd ..");

                env::set_current_dir(parent_path).expect("changing directory failed");
            }
        }
    } else {
        println!(
            "rev-list stderr: {}",
            String::from_utf8(git_rev_list_output.stderr).unwrap()
        );

        process::exit(1);
    }
}
<|endoftext|>


<commit_before>use graph::{Edge, Graph};
use adjacency_matrix::AdjacencyMatrix;

use std::usize;

// maximum_flow returns the maximum flow from source to sink in g.
pub fn maximum_flow(g: &Graph, source: usize, sink: usize) -> u32 {
    // Initially, the residual flow graph of g is just the same as g.
    let mut residual_flow_graph = AdjacencyMatrix::from_graph(g);

    let mut flow = 0;
    loop {
        let path_capacity = residual_flow_graph.add_augmenting_path(source, sink);
        if path_capacity <= 0 {
            return flow;
        }
        flow += path_capacity;
    }
}

impl AdjacencyMatrix {
    // addAugmentingPath looks for an augmenting path from source to sink in the residual flow
    // graph.
    // If an augmenting path is found, addAugmentingPath updates the residual flow graph to reflect
    // the addition of the augmenting path, and returns the capacity of the augmenting path.
    // If no augmenting path is found, addAugmentingPath returns 0.
    fn add_augmenting_path(&mut self, source: usize, sink: usize) -> u32 {
        let mut parents = vec![usize::MAX; self.size()];

        for Edge { x, y } in self.breadth_first_search(source) {
            parents[y] = x;
            if y == sink {
                // Abort the BFS.
                break;
            }
        }

        // self.breadth_first_search(source, |Edge { x, y }| {
        //     parents[y] = x;
        //     // Return true to abort the BFS.
        //     y == sink
        // });

        self.substract_path(&parents, sink)
    }

    // substractPath substracts the path described by parents and end from the residual flow graph,
    // and returns the capacity of the path.
    fn substract_path(&mut self, parents: &Vec<usize>, end: usize) -> u32 {
        let capacity = self.path_capacity(parents, end);

        for Edge {x, y} in edges(parents, end) {
            self[x][y] -= capacity;
            self[y][x] += capacity;
        }

        capacity
    }

    // pathCapacity returns the capacity of the path described by parents and end in the residual
    // flow graph.
    fn path_capacity(&self, parents: &Vec<usize>, end: usize) -> u32 {
        let edges = edges(parents, end);
        let capacities = edges.iter().map(|edge| self[edge.x][edge.y]);

        match capacities.min() {
            Some(capacity) => capacity,
            None => 0,
        }
    }
}

// edges returns the edges of the path described by parents and end.
fn edges(parents: &Vec<usize>, mut end: usize) -> Vec<Edge> {
    let mut edges = vec![];

    while parents[end] < usize::MAX {
        let edge = Edge { x: parents[end], y: end };
        edges.push(edge);
        end = parents[end];
    }

    edges.reverse();
    edges
}
<commit_msg>[edge_connectivity/rust] Return None instead of 0 when no path is found<commit_after>use graph::{Edge, Graph};
use adjacency_matrix::AdjacencyMatrix;

use std::usize;

// maximum_flow returns the maximum flow from source to sink in g.
pub fn maximum_flow(g: &Graph, source: usize, sink: usize) -> u32 {
    // Initially, the residual flow graph of g is just the same as g.
    let mut residual_flow_graph = AdjacencyMatrix::from_graph(g);

    let mut flow = 0;
    while let Some(path_capacity) = residual_flow_graph.add_augmenting_path(source, sink) {
        flow += path_capacity;
    }
    flow
}

impl AdjacencyMatrix {
    // addAugmentingPath looks for an augmenting path from source to sink in the residual flow
    // graph.
    // If an augmenting path is found, addAugmentingPath updates the residual flow graph to reflect
    // the addition of the augmenting path, and returns the capacity of the augmenting path.
    // If no augmenting path is found, addAugmentingPath returns None.
    fn add_augmenting_path(&mut self, source: usize, sink: usize) -> Option<u32> {
        let mut parents = vec![usize::MAX; self.size()];

        for Edge { x, y } in self.breadth_first_search(source) {
            parents[y] = x;
            if y == sink {
                // Abort the BFS.
                break;
            }
        }

        // self.breadth_first_search(source, |Edge { x, y }| {
        //     parents[y] = x;
        //     // Return true to abort the BFS.
        //     y == sink
        // });

        self.substract_path(&parents, sink)
    }

    // substractPath substracts the path described by parents and end from the residual flow graph,
    // and returns the capacity of the path.
    fn substract_path(&mut self, parents: &Vec<usize>, end: usize) -> Option<u32> {
        let capacity = self.path_capacity(parents, end);

        if let Some(c) = capacity {
            for Edge {x, y} in edges(parents, end) {
                self[x][y] -= c;
                self[y][x] += c;
            }
        }

        capacity
    }

    // pathCapacity returns the capacity of the path described by parents and end in the residual
    // flow graph.
    fn path_capacity(&self, parents: &Vec<usize>, end: usize) -> Option<u32> {
        let edges = edges(parents, end);
        let capacities = edges.iter().map(|edge| self[edge.x][edge.y]);
        capacities.min()
    }
}

// edges returns the edges of the path described by parents and end.
fn edges(parents: &Vec<usize>, mut end: usize) -> Vec<Edge> {
    let mut edges = vec![];

    while parents[end] < usize::MAX {
        let edge = Edge { x: parents[end], y: end };
        edges.push(edge);
        end = parents[end];
    }

    edges.reverse();
    edges
}
<|endoftext|>