<commit_before>extern crate graphics;
extern crate piston;
extern crate opengl_graphics;
extern crate freetype;

use piston::event::*;
use piston::input::*;
use opengl_graphics::GlGraphics;

use field;
use font;
use settings;

struct Vec2f {
    x: f64,
    y: f64
}

pub struct App {
    settings: settings::Settings,
    mouse_coords: Vec2f,
    field: field::Field,
    selected_cell: Option<field::Coords>,
    conflicting_cell: Option<field::Coords>
}

impl App {
    pub fn new(settings: settings::Settings) -> App {
        App {
            settings: settings,
            mouse_coords: Vec2f{ x: 0.0, y: 0.0 },
            field: field::Field::new(),
            selected_cell: None,
            conflicting_cell: None
        }
    }

    pub fn on_render(&mut self, args: &RenderArgs,
                     gl: &mut GlGraphics, face: &mut freetype::Face) {
        gl.draw(args.viewport(), |c, g| {
            use graphics::*;
            clear([1.0; 4], g);

            let pointed_cell = field::Coords{
                x: (self.mouse_coords.x / self.settings.cell_size.x as f64)
                    .floor() as u8,
                y: (self.mouse_coords.y / self.settings.cell_size.y as f64)
                    .floor() as u8 };
            rectangle([0.95, 0.95, 0.95, 1.0],
                      [(pointed_cell.x as f64) * self.settings.cell_size.x,
                       (pointed_cell.y as f64) * self.settings.cell_size.y,
                       self.settings.cell_size.x, self.settings.cell_size.y],
                      c.transform, g);

            for y in 0..9 {
                for x in 0..9 {
                    let cell = self.field.get_cell(x, y);
                    if cell.fixed {
                        rectangle([0.9, 0.9, 0.9, 1.0],
                            [(x as f64) * self.settings.cell_size.x,
                             (y as f64) * self.settings.cell_size.y,
                             self.settings.cell_size.x,
                             self.settings.cell_size.y],
                            c.transform, g);
                    }
                }
            }

            if let Some(ref cell) = self.selected_cell {
                if let Some(digit) = self.field.get_cell(cell.x, cell.y).digit {
                    for y in 0..9 {
                        for x in 0..9 {
                            if let Some(other_digit) =
                                    self.field.get_cell(x, y).digit {
                                if other_digit == digit {
                                    rectangle([0.8, 0.8, 0.9, 1.0],
                                        [(x as f64) * self.settings.cell_size.x,
                                         (y as f64) * self.settings.cell_size.y,
                                         self.settings.cell_size.x,
                                         self.settings.cell_size.y],
                                        c.transform, g);
                                }
                            }
                        }
                    }
                }
            }

            if let Some(ref cell) = self.conflicting_cell {
                rectangle([0.9, 0.8, 0.8, 1.0],
                          [(cell.x as f64) * self.settings.cell_size.x,
                           (cell.y as f64) * self.settings.cell_size.y,
                           self.settings.cell_size.x, self.settings.cell_size.y],
                          c.transform, g);
            }

            if let Some(ref cell) = self.selected_cell {
                rectangle([0.8, 0.9, 0.8, 1.0],
                          [(cell.x as f64) * self.settings.cell_size.x,
                           (cell.y as f64) * self.settings.cell_size.y,
                           self.settings.cell_size.x, self.settings.cell_size.y],
                          c.transform, g);
            }

            for y in 0..9 {
                for x in 0..9 {
                    if let Some(ref digit) = self.field.cells[y][x].digit {
                        let transform = c.transform.trans(
                            (x as f64) * self.settings.cell_size.x +
                                self.settings.text_offset.x,
                            (y as f64) * self.settings.cell_size.y +
                                self.settings.text_offset.y);
                        font::render_text(face, g, transform,
                                    &digit.to_string());
                    }
                }
            }

            for n in 1..9 {
                let mut thick = 2.0;
                if n % 3 == 0 {
                    thick = 8.0;
                }
                rectangle([0.0, 0.0, 0.0, 1.0],
                          [(n as f64) * self.settings.cell_size.x - thick / 2.0,
                           0.0, thick / 2.0, self.settings.wind_size.y],
                           c.transform, g);
                rectangle([0.0, 0.0, 0.0, 1.0],
                          [0.0, (n as f64) * self.settings.cell_size.y -
                                thick / 2.0,
                           self.settings.wind_size.x, thick / 2.0],
                           c.transform, g);
            }
        });
    }

    pub fn on_button_press(&mut self, button: &Button) {
        match button {
            &Button::Keyboard(key) => {
                self.on_key_down(&key);
            },
            &Button::Mouse(button) => {
                self.on_mouse_click(&button);
            }
        }
    }

    fn on_key_down(&mut self, pressed_key: &Key) {
        let key_digit_mapping = [
            (Key::D1, 1), (Key::D2, 2), (Key::D3, 3),
            (Key::D4, 4), (Key::D5, 5), (Key::D6, 6),
            (Key::D7, 7), (Key::D8, 8), (Key::D9, 9) ];
        for &(key, digit) in key_digit_mapping.iter() {
            if pressed_key == &key {
                if let Some(ref cell) = self.selected_cell {
                    if !self.field.get_cell(cell.x, cell.y).fixed {
                        match self.field.find_conflicts(cell, digit) {
                            Some(coords) => {
                                self.conflicting_cell = Some(coords);
                            },
                            None => {
                                self.field.get_cell(cell.x, cell.y).digit =
                                    Some(digit);
                                self.conflicting_cell = None;
                            }
                        }
                    }
                }
            }
        }
        if pressed_key == &Key::Backspace {
            if let Some(ref cell) = self.selected_cell {
                if !self.field.get_cell(cell.x, cell.y).fixed {
                    self.field.get_cell(cell.x, cell.y).digit = None;
                    self.conflicting_cell = None;
                }
            }
        }
        if pressed_key == &Key::S {
            self.field.fill_solution();
        }
        if pressed_key == &Key::R {
            self.field.fill_random();
        }
    }

    fn on_mouse_click(&mut self, button: &MouseButton) {
        if let &MouseButton::Left = button {
            self.selected_cell = Some(field::Coords{
                x: (self.mouse_coords.x / self.settings.cell_size.x) as u8,
                y: (self.mouse_coords.y / self.settings.cell_size.y) as u8 });
        }
    }

    pub fn on_mouse_move(&mut self, args: &[f64; 2]) {
        self.mouse_coords.x = args[0];
        self.mouse_coords.y = args[1];
    }
}
<commit_msg>Small fixes<commit_after>extern crate graphics;
extern crate piston;
extern crate opengl_graphics;
extern crate freetype;

use piston::event::*;
use piston::input::*;
use opengl_graphics::GlGraphics;

use field;
use font;
use settings;

struct Vec2f {
    x: f64,
    y: f64
}

pub struct App {
    settings: settings::Settings,
    mouse_coords: Vec2f,
    field: field::Field,
    selected_cell: Option<field::Coords>,
    conflicting_cell: Option<field::Coords>
}

impl App {
    pub fn new(settings: settings::Settings) -> App {
        App {
            settings: settings,
            mouse_coords: Vec2f{ x: 0.0, y: 0.0 },
            field: field::Field::new(),
            selected_cell: None,
            conflicting_cell: None
        }
    }

    pub fn on_render(&mut self, args: &RenderArgs,
                     gl: &mut GlGraphics, face: &mut freetype::Face) {
        gl.draw(args.viewport(), |c, g| {
            use graphics::*;
            clear([1.0; 4], g);

            let pointed_cell = field::Coords{
                x: (self.mouse_coords.x / self.settings.cell_size.x as f64)
                    .floor() as u8,
                y: (self.mouse_coords.y / self.settings.cell_size.y as f64)
                    .floor() as u8 };
            rectangle([0.95, 0.95, 0.95, 1.0],
                      [(pointed_cell.x as f64) * self.settings.cell_size.x,
                       (pointed_cell.y as f64) * self.settings.cell_size.y,
                       self.settings.cell_size.x, self.settings.cell_size.y],
                      c.transform, g);

            for y in 0..9 {
                for x in 0..9 {
                    let cell = self.field.get_cell(x, y);
                    if cell.fixed {
                        rectangle([0.9, 0.9, 0.9, 1.0],
                            [(x as f64) * self.settings.cell_size.x,
                             (y as f64) * self.settings.cell_size.y,
                             self.settings.cell_size.x,
                             self.settings.cell_size.y],
                            c.transform, g);
                    }
                }
            }

            if let Some(ref cell) = self.selected_cell {
                if let Some(digit) = self.field.get_cell(cell.x, cell.y).digit {
                    for y in 0..9 {
                        for x in 0..9 {
                            if let Some(other_digit) =
                                    self.field.get_cell(x, y).digit {
                                if other_digit == digit {
                                    rectangle([0.8, 0.8, 0.9, 1.0],
                                        [(x as f64) * self.settings.cell_size.x,
                                         (y as f64) * self.settings.cell_size.y,
                                         self.settings.cell_size.x,
                                         self.settings.cell_size.y],
                                        c.transform, g);
                                }
                            }
                        }
                    }
                }
            }

            if let Some(ref cell) = self.conflicting_cell {
                rectangle([0.9, 0.8, 0.8, 1.0],
                          [(cell.x as f64) * self.settings.cell_size.x,
                           (cell.y as f64) * self.settings.cell_size.y,
                           self.settings.cell_size.x, self.settings.cell_size.y],
                          c.transform, g);
            }

            if let Some(ref cell) = self.selected_cell {
                rectangle([0.8, 0.9, 0.8, 1.0],
                          [(cell.x as f64) * self.settings.cell_size.x,
                           (cell.y as f64) * self.settings.cell_size.y,
                           self.settings.cell_size.x, self.settings.cell_size.y],
                          c.transform, g);
            }

            for y in 0..9 {
                for x in 0..9 {
                    if let Some(ref digit) = self.field.cells[y][x].digit {
                        let transform = c.transform.trans(
                            (x as f64) * self.settings.cell_size.x +
                                self.settings.text_offset.x,
                            (y as f64) * self.settings.cell_size.y +
                                self.settings.text_offset.y);
                        font::render_text(face, g, transform,
                                    &digit.to_string());
                    }
                }
            }

            for n in 1..9 {
                let mut thick = 2.0;
                if n % 3 == 0 {
                    thick = 8.0;
                }
                rectangle([0.0, 0.0, 0.0, 1.0],
                          [(n as f64) * self.settings.cell_size.x - thick / 2.0,
                           0.0, thick / 2.0, self.settings.wind_size.y],
                           c.transform, g);
                rectangle([0.0, 0.0, 0.0, 1.0],
                          [0.0, (n as f64) * self.settings.cell_size.y -
                                thick / 2.0,
                           self.settings.wind_size.x, thick / 2.0],
                           c.transform, g);
            }
        });
    }

    pub fn on_button_press(&mut self, button: &Button) {
        match button {
            &Button::Keyboard(key) => {
                self.on_key_down(&key);
            },
            &Button::Mouse(button) => {
                self.on_mouse_click(&button);
            }
        }
    }

    fn on_key_down(&mut self, pressed_key: &Key) {
        let key_digit_mapping = [
            (Key::D1, 1), (Key::D2, 2), (Key::D3, 3),
            (Key::D4, 4), (Key::D5, 5), (Key::D6, 6),
            (Key::D7, 7), (Key::D8, 8), (Key::D9, 9) ];
        for &(key, digit) in key_digit_mapping.iter() {
            if pressed_key == &key {
                if let Some(ref cell) = self.selected_cell {
                    if !self.field.get_cell(cell.x, cell.y).fixed {
                        match self.field.find_conflicts(cell, digit) {
                            Some(coords) => {
                                self.conflicting_cell = Some(coords);
                            },
                            None => {
                                self.field.get_cell(cell.x, cell.y).digit =
                                    Some(digit);
                                self.conflicting_cell = None;
                            }
                        }
                    }
                }
            }
        }
        if pressed_key == &Key::Backspace {
            if let Some(ref cell) = self.selected_cell {
                if !self.field.get_cell(cell.x, cell.y).fixed {
                    self.field.get_cell(cell.x, cell.y).digit = None;
                    self.conflicting_cell = None;
                }
            }
        }
        if pressed_key == &Key::S {
            self.field.fill_solution();
            self.conflicting_cell = None;
            self.selected_cell = None;
        }
        if pressed_key == &Key::R {
            self.field.fill_random();
            self.conflicting_cell = None;
            self.selected_cell = None;
        }
    }

    fn on_mouse_click(&mut self, button: &MouseButton) {
        if let &MouseButton::Left = button {
            self.selected_cell = Some(field::Coords{
                x: (self.mouse_coords.x / self.settings.cell_size.x) as u8,
                y: (self.mouse_coords.y / self.settings.cell_size.y) as u8 });
        }
    }

    pub fn on_mouse_move(&mut self, args: &[f64; 2]) {
        self.mouse_coords.x = args[0];
        self.mouse_coords.y = args[1];
    }
}
<|endoftext|>


<commit_before>use env::Env;
use var::Var;
use source::{Src,Next};
use logic::LogicFn;
use def::DefBlock;

use std::collections::HashMap;

/// Creates a possible path from a dot-seperated string
///
/// Returns path, and final symbol
/// Eg: 'items.bag.coins' becomes -> (Some(Vec['items','bag']), 'coins')
pub fn as_path<'a> (lookup: &'a str) -> (Option<Vec<&'a str>>, &'a str) {
    let mut lookups: Vec<&'a str> = lookup.split_terminator('.').collect();
    let item = lookups.pop().unwrap();

    let path;
    if lookups.len() > 0 { path = Some(lookups); }
    else { path = None }

    (path,item)
}

/// Primary Evaluation trait must be implemented to run Evaluator
///
///
pub trait Eval {
    /// Get method to retrieve variable from Rust side
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var>;

    fn as_path<'a> (&self, lookup: &'a str) -> (Option<Vec<&'a str>>, &'a str) {
        as_path(lookup)
    }

    fn get_path (&self, lookup: &str) -> Option<Var> {
        let (path,lookup) = self.as_path(lookup);
        self.get(path, lookup)
    }

    /// Returns final ref or var, and if it is a var
    fn get_last (&self, lookup: &str) -> Option<(Var, bool)>;

    /// Expects var to be written to underlying mem/store in Rust
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var);

    fn set_path (&mut self, lookup: &str, v: Var) {
        let (path,lookup) = self.as_path(&lookup);
        self.set(path,lookup, v);
    }

    /// A custom callable function
    ///
    /// Var represents variable to mutate
    /// Fun is the function name
    /// Vars are any additional arguments
    /// Can optionally return variable back to lichen
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var>;
}

pub struct Evaluator<'e> {
    env: &'e mut Env,
    node_stack: Vec<String>,
}

impl<'e> Iterator for Evaluator<'e> {

        type Item = (Vec<Var>, Option<Next>); //here we only return node name as an option to advance
        fn next(&mut self) -> Option<Self::Item> {
            if let Some(nn) = self.node_stack.pop() {
                if let Some(r) = self.run(&nn) {
                    // reset node if necessary
                    if let Some(ref next) = r.1 {
                        match next {
                            &Next::Restart(ref nn) => {
                                if let &Some(ref nn) = nn {
                                    if let Some(b) = self.env.src.get_mut(nn) {
                                        b.idx = 0;
                                    }
                                }
                            }
                            _ => {}, // we handle the rest during Run, for convenience
                        }
                    }

                    Some(r)
                }
                else { self.next() }
            }
            else { None }
        }
    }

impl<'e> Evaluator<'e> {
    /// Evaluator by default starts on the node named 'root'
    pub fn new (env: &'e mut Env) -> Evaluator<'e> {
        Evaluator {
            env: env,
            node_stack: vec!["root".to_owned()],
        }
    }

    /// Consumes Evaluator for saving state
    ///
    /// You should save the Env state as well, as it's external to the Evaluator
    pub fn save (self) -> EvaluatorState {
        EvaluatorState {
            node_stack: self.node_stack,
        }
    }

    /// Manually advances Evaluator to next node
    pub fn advance (&mut self, node: String) {
        // successful advance clears out stack
        self.node_stack.clear();
        self.node_stack.push(node);
    }

    pub fn resolve (s: &str, logic: &HashMap<String,LogicFn>, def: &HashMap<String,DefBlock>) -> Option<Var> {
        if let Some(ref lfn) = logic.get(s) {
            if let Some(val_) = lfn.run(&def, &logic) {
                return Some(val_.into())
            }
        }
        else if let Some((v,res)) = def.get_last(s) {
            if res { return Some(v) }
        }

        None
    }

    /// Manually run the Evaluator, starting at node specified
    pub fn run (&mut self, node_name: &str)
                -> Option<(Vec<Var>, Option<Next>)>
    {
        if let Some(b) = self.env.src.get_mut(node_name) {
            b.visited = true;

            if let Some(src) = b.src.get(b.idx) {
                self.node_stack.push(node_name.to_owned()); //more to iterate through?
                b.idx += 1;

                match src {
                    &Src::Or(_,_) => {
                        if !b.or_valid {
                            return None
                        }
                        else { b.or_valid = false; } //reset
                    }
                    &Src::If(_,_,_) => { b.or_valid = true; }
                    // anything else resets above or-logic
                    _ => { b.or_valid = false; },
                }

                let (mut vars, next) = src.eval(&mut b.logic,
                                                &mut self.env.def,
                                                &mut self.env.fun);
                let has_return = (vars.len() > 0) || next.is_some();

                // reset when if is successful
                if has_return { b.or_valid = false; }

                for var in vars.iter_mut() {
                    let mut val = None;

                    match var {
                        &mut Var::Sym(ref mut s) => { // resolve symbol refs
                            val = Evaluator::resolve(s, &b.logic, &self.env.def);
                            // NOTE: otherwise we silently fail
                        },
                        &mut Var::String(ref mut s) => { //format string
                            let mut fs = String::new();
                            let mut sym = String::new();
                            let mut in_sym = false;

                            for c in s.chars() {
                                if (c == ' ' || c == '`') && !sym.is_empty() {
                                    if let Some(v) = Evaluator::resolve(&sym, &b.logic, &self.env.def) {
                                        fs.push_str(&v.to_string());
                                    }
                                    else {
                                        fs.push_str(&sym); //push as non-ref sym again
                                        // NOTE: we should consider failing silently (dont push)
                                    }

                                    if c == '`' { in_sym = true; }
                                    else {
                                        in_sym = false;
                                        sym.clear();
                                        fs.push(' ');
                                    }
                                }
                                else if c == '`' { in_sym = true; }
                                else {
                                    if in_sym { sym.push(c); }
                                    else { fs.push(c); }
                                }
                            }

                            if !sym.is_empty() {
                                if let Some(v) = Evaluator::resolve(&sym, &b.logic, &self.env.def) {
                                    fs.push_str(&v.to_string());
                                }
                                else {
                                    fs.push_str(&sym);
                                }
                            }

                            *s = fs;
                        },
                        _ => {}
                    }

                    if let Some(val) = val {
                        *var = val;
                    }
                }

                if let Some(ref next) = next {
                    let idx = b.idx; // save for 'back'
                    b.idx = 0; // clear our place in the source evaluation
                    // NOTE: await and select clear stack on advance
                    match next {
                        &Next::Now(ref nn) => { // immediate advance clears node stack
                            self.node_stack.clear();
                            self.node_stack.push(nn.clone());
                        },
                        &Next::Call(ref nn) => { // callback nodes add to stack
                            self.node_stack.push(nn.clone());
                        },
                        &Next::Back => {
                            b.idx = idx; // reset so we can pickup afterwards
                            self.node_stack.pop();
                        },
                        &Next::Restart(ref nn) => {
                            if nn.is_none() { b.idx = 0; }
                            // NOTE: see iterator for other side of this
                        },
                        &Next::Clear => {
                            self.node_stack.clear();
                            self.node_stack.push(b.name.to_owned());
                        },
                        &Next::Exit => { self.node_stack.clear(); },
                        _ => {},
                    }
                }

                if has_return {
                    return Some((vars,next))
                }
                else {
                    return None
                }
            }
            else { b.idx = 0; } //reset
        }

        None
    }
}

#[derive(Clone,Debug)]
pub struct EvaluatorState {
    node_stack: Vec<String>,
}

impl EvaluatorState {
    pub fn to_eval<'e> (self, env: &'e mut Env) -> Evaluator<'e> {
        Evaluator {
            env: env,
            node_stack: self.node_stack,
        }
    }

    pub fn as_eval<'e> (&self, env: &'e mut Env) -> Evaluator<'e> {
        self.clone().to_eval(env)
    }
}
<commit_msg>reset logic<commit_after>use env::Env;
use var::Var;
use source::{Src,Next};
use logic::LogicFn;
use def::DefBlock;

use std::collections::HashMap;

/// Creates a possible path from a dot-seperated string
///
/// Returns path, and final symbol
/// Eg: 'items.bag.coins' becomes -> (Some(Vec['items','bag']), 'coins')
pub fn as_path<'a> (lookup: &'a str) -> (Option<Vec<&'a str>>, &'a str) {
    let mut lookups: Vec<&'a str> = lookup.split_terminator('.').collect();
    let item = lookups.pop().unwrap();

    let path;
    if lookups.len() > 0 { path = Some(lookups); }
    else { path = None }

    (path,item)
}

/// Primary Evaluation trait must be implemented to run Evaluator
///
///
pub trait Eval {
    /// Get method to retrieve variable from Rust side
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var>;

    fn as_path<'a> (&self, lookup: &'a str) -> (Option<Vec<&'a str>>, &'a str) {
        as_path(lookup)
    }

    fn get_path (&self, lookup: &str) -> Option<Var> {
        let (path,lookup) = self.as_path(lookup);
        self.get(path, lookup)
    }

    /// Returns final ref or var, and if it is a var
    fn get_last (&self, lookup: &str) -> Option<(Var, bool)>;

    /// Expects var to be written to underlying mem/store in Rust
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var);

    fn set_path (&mut self, lookup: &str, v: Var) {
        let (path,lookup) = self.as_path(&lookup);
        self.set(path,lookup, v);
    }

    /// A custom callable function
    ///
    /// Var represents variable to mutate
    /// Fun is the function name
    /// Vars are any additional arguments
    /// Can optionally return variable back to lichen
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var>;
}

pub struct Evaluator<'e> {
    env: &'e mut Env,
    node_stack: Vec<String>,
}

impl<'e> Iterator for Evaluator<'e> {

        type Item = (Vec<Var>, Option<Next>); //here we only return node name as an option to advance
        fn next(&mut self) -> Option<Self::Item> {
            if let Some(nn) = self.node_stack.pop() {
                if let Some(r) = self.run(&nn) {
                    // reset node if necessary
                    if let Some(ref next) = r.1 {
                        match next {
                            &Next::Restart(ref nn) => {
                                if let &Some(ref nn) = nn {
                                    if let Some(b) = self.env.src.get_mut(nn) {
                                        b.idx = 0;
                                    }
                                }
                            }
                            _ => {}, // we handle the rest during Run, for convenience
                        }
                    }

                    Some(r)
                }
                else { self.next() }
            }
            else { None }
        }
    }

impl<'e> Evaluator<'e> {
    /// Evaluator by default starts on the node named 'root'
    pub fn new (env: &'e mut Env) -> Evaluator<'e> {
        Evaluator {
            env: env,
            node_stack: vec!["root".to_owned()],
        }
    }

    /// Consumes Evaluator for saving state
    ///
    /// You should save the Env state as well, as it's external to the Evaluator
    pub fn save (self) -> EvaluatorState {
        EvaluatorState {
            node_stack: self.node_stack,
        }
    }

    /// Manually advances Evaluator to next node
    pub fn advance (&mut self, node: String) {
        // successful advance clears out stack
        self.node_stack.clear();
        self.node_stack.push(node);
    }

    pub fn resolve (s: &str, logic: &HashMap<String,LogicFn>, def: &HashMap<String,DefBlock>) -> Option<Var> {
        if let Some(ref lfn) = logic.get(s) {
            if let Some(val_) = lfn.run(&def, &logic) {
                return Some(val_.into())
            }
        }
        else if let Some((v,res)) = def.get_last(s) {
            if res { return Some(v) }
        }

        None
    }

    /// Manually run the Evaluator, starting at node specified
    pub fn run (&mut self, node_name: &str)
                -> Option<(Vec<Var>, Option<Next>)>
    {
        if let Some(b) = self.env.src.get_mut(node_name) {
            b.visited = true;

            if let Some(src) = b.src.get(b.idx) {
                self.node_stack.push(node_name.to_owned()); //more to iterate through?
                b.idx += 1;

                match src {
                    &Src::Or(_,_) => {
                        if !b.or_valid {
                            return None
                        }
                        else { b.or_valid = false; } //reset
                    }
                    &Src::If(_,_,_) => { b.or_valid = true; }
                    // anything else resets above or-logic
                    _ => { b.or_valid = false; },
                }

                let (mut vars, next) = src.eval(&mut b.logic,
                                                &mut self.env.def,
                                                &mut self.env.fun);
                let has_return = (vars.len() > 0) || next.is_some();

                // reset when if is successful
                if has_return { b.or_valid = false; }

                for var in vars.iter_mut() {
                    let mut val = None;

                    match var {
                        &mut Var::Sym(ref mut s) => { // resolve symbol refs
                            val = Evaluator::resolve(s, &b.logic, &self.env.def);
                            // NOTE: otherwise we silently fail
                        },
                        &mut Var::String(ref mut s) => { //format string
                            let mut fs = String::new();
                            let mut sym = String::new();
                            let mut in_sym = false;

                            for c in s.chars() {
                                if (c == ' ' || c == '`') && !sym.is_empty() {
                                    if let Some(v) = Evaluator::resolve(&sym, &b.logic, &self.env.def) {
                                        fs.push_str(&v.to_string());
                                    }
                                    else {
                                        fs.push_str(&sym); //push as non-ref sym again
                                        // NOTE: we should consider failing silently (dont push)
                                    }

                                    if c == '`' { in_sym = true; }
                                    else {
                                        in_sym = false;
                                        sym.clear();
                                        fs.push(' ');
                                    }
                                }
                                else if c == '`' { in_sym = true; }
                                else {
                                    if in_sym { sym.push(c); }
                                    else { fs.push(c); }
                                }
                            }

                            if !sym.is_empty() {
                                if let Some(v) = Evaluator::resolve(&sym, &b.logic, &self.env.def) {
                                    fs.push_str(&v.to_string());
                                }
                                else {
                                    fs.push_str(&sym);
                                }
                            }

                            *s = fs;
                        },
                        _ => {}
                    }

                    if let Some(val) = val {
                        *var = val;
                    }
                }

                if let Some(ref next) = next {
                    let idx = b.idx; // save for 'back'
                    b.idx = 0; // clear our place in the source evaluation
                    // NOTE: await and select clear stack on advance
                    match next {
                        &Next::Now(ref nn) => { // immediate advance clears node stack
                            self.node_stack.clear();
                            self.node_stack.push(nn.clone());
                        },
                        &Next::Call(ref nn) => { // callback nodes add to stack
                            self.node_stack.push(nn.clone());
                        },
                        &Next::Back => {
                            b.idx = idx; // reset so we can pickup afterwards
                            self.node_stack.pop();
                        },
                        &Next::Restart(ref nn) => {
                            if nn.is_some() { b.idx = idx; }
                            // NOTE: see iterator for other side of this
                        },
                        &Next::Clear => {
                            self.node_stack.clear();
                            self.node_stack.push(b.name.to_owned());
                        },
                        &Next::Exit => { self.node_stack.clear(); },
                        _ => {},
                    }
                }

                if has_return {
                    return Some((vars,next))
                }
                else {
                    return None
                }
            }
            else { b.idx = 0; } //reset
        }

        None
    }
}

#[derive(Clone,Debug)]
pub struct EvaluatorState {
    node_stack: Vec<String>,
}

impl EvaluatorState {
    pub fn to_eval<'e> (self, env: &'e mut Env) -> Evaluator<'e> {
        Evaluator {
            env: env,
            node_stack: self.node_stack,
        }
    }

    pub fn as_eval<'e> (&self, env: &'e mut Env) -> Evaluator<'e> {
        self.clone().to_eval(env)
    }
}
<|endoftext|>


<commit_before>use super::object::Object;
use super::lexer::Lexer;
use super::parser::Parser;
use super::ast::Program;
use super::ast::Statement;
use super::ast::Expression;

pub fn eval(program: Program) -> Object {
    let mut result = Object::Null;

    for stmt in program.statements {
        result = match stmt {
            Statement::Expression { ref expression, .. } => eval_expr(expression),
            _ => Object::Null
        };
    }

    result
}

fn eval_expr(expr: &Expression) -> Object {
    match *expr {
        Expression::IntegerLiteral { value, .. } => Object::Integer(value),
        Expression::Boolean { value, .. } => Object::Boolean(value),
        _ => Object::Null
    }
}

#[cfg(test)]
fn test_eval(input: &str) -> Object {
    let mut l = Lexer::new(input.to_string());
    let mut p = Parser::new(&mut l);
    let program = p.parse_program();

    eval(program)
}

#[cfg(test)]
fn check_integer_object(obj: Object, expected: i64) {
    match obj {
        Object::Integer(val) => {
            assert!(val == expected,
                    "Object has wrong value. Got {}, want {}",
                    val,
                    expected);
        },
        _ => panic!("Object is not an Integer. Got {:?}", obj)
    }
}

#[cfg(test)]
fn check_boolean_object(obj: Object, expected: bool) {
    match obj {
        Object::Boolean(val) => {
            assert!(val == expected,
                    "Object has wrong value. Got {}, want {}",
                    val,
                    expected);
        },
        _ => panic!("Object is not an Boolean. Got {:?}", obj)
    }
}

#[test]
fn test_eval_integer_expression() {
    let tests = vec![
        ("5", 5),
        ("10", 10)
    ];

    for (input, expected) in tests {
        let evaluated = test_eval(input);
        check_integer_object(evaluated, expected);
    }
}

#[test]
fn test_eval_boolean_expression() {
    let tests = vec![
        ("true", true),
        ("false", false)
    ];

    for (input, expected) in tests {
        let evaluated = test_eval(input);
        check_boolean_object(evaluated, expected);
    }
}<commit_msg>Small refactoring (idk for now if it's useful).<commit_after>use super::object::Object;

use super::ast::Program;
use super::ast::Statement;
use super::ast::Expression;

const TRUE: Object = Object::Boolean(true);
const FALSE: Object = Object::Boolean(false);

pub fn eval(program: Program) -> Object {
    let mut result = Object::Null;

    for stmt in program.statements {
        result = match stmt {
            Statement::Expression { ref expression, .. } => eval_expr(expression),
            _ => Object::Null
        };
    }

    result
}

fn eval_expr(expr: &Expression) -> Object {
    match *expr {
        Expression::IntegerLiteral { value, .. } => Object::Integer(value),
        Expression::Boolean { value, .. } => if value { TRUE } else { FALSE },
        _ => Object::Null
    }
}

#[cfg(test)]
use super::lexer::Lexer;
#[cfg(test)]
use super::parser::Parser;

#[cfg(test)]
fn test_eval(input: &str) -> Object {
    let mut l = Lexer::new(input.to_string());
    let mut p = Parser::new(&mut l);
    let program = p.parse_program();

    eval(program)
}

#[cfg(test)]
fn check_integer_object(obj: Object, expected: i64) {
    match obj {
        Object::Integer(val) => {
            assert!(val == expected,
                    "Object has wrong value. Got {}, want {}",
                    val,
                    expected);
        },
        _ => panic!("Object is not an Integer. Got {:?}", obj)
    }
}

#[cfg(test)]
fn check_boolean_object(obj: Object, expected: bool) {
    match obj {
        Object::Boolean(val) => {
            assert!(val == expected,
                    "Object has wrong value. Got {}, want {}",
                    val,
                    expected);
        },
        _ => panic!("Object is not an Boolean. Got {:?}", obj)
    }
}

#[test]
fn test_eval_integer_expression() {
    let tests = vec![
        ("5", 5),
        ("10", 10)
    ];

    for (input, expected) in tests {
        let evaluated = test_eval(input);
        check_integer_object(evaluated, expected);
    }
}

#[test]
fn test_eval_boolean_expression() {
    let tests = vec![
        ("true", true),
        ("false", false)
    ];

    for (input, expected) in tests {
        let evaluated = test_eval(input);
        check_boolean_object(evaluated, expected);
    }
}<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use crate::future::{MaybeDone, maybe_done};
use core::fmt;
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use pin_utils::unsafe_pinned;
use super::assert_future;

macro_rules! generate {
    ($(
        $(#[$doc:meta])*
        ($Join:ident, <$($Fut:ident),*>),
    )*) => ($(
        $(#[$doc])*
        #[must_use = "futures do nothing unless you `.await` or poll them"]
        pub struct $Join<$($Fut: Future),*> {
            $($Fut: MaybeDone<$Fut>,)*
        }

        impl<$($Fut),*> fmt::Debug for $Join<$($Fut),*>
        where
            $(
                $Fut: Future + fmt::Debug,
                $Fut::Output: fmt::Debug,
            )*
        {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.debug_struct(stringify!($Join))
                    $(.field(stringify!($Fut), &self.$Fut))*
                    .finish()
            }
        }

        impl<$($Fut: Future),*> $Join<$($Fut),*> {
            fn new($($Fut: $Fut),*) -> $Join<$($Fut),*> {
                $Join {
                    $($Fut: maybe_done($Fut)),*
                }
            }
            $(
                unsafe_pinned!($Fut: MaybeDone<$Fut>);
            )*
        }

        impl<$($Fut: Future),*> Future for $Join<$($Fut),*> {
            type Output = ($($Fut::Output),*);

            fn poll(
                mut self: Pin<&mut Self>, cx: &mut Context<'_>
            ) -> Poll<Self::Output> {
                let mut all_done = true;
                $(
                    all_done &= self.as_mut().$Fut().poll(cx).is_ready();
                )*

                if all_done {
                    Poll::Ready(($(self.as_mut().$Fut().take_output().unwrap()), *))
                } else {
                    Poll::Pending
                }
            }
        }
    )*)
}

generate! {
    /// Future for the [`join`](join()) function.
    (Join, <Fut1, Fut2>),

    /// Future for the [`join3`] function.
    (Join3, <Fut1, Fut2, Fut3>),

    /// Future for the [`join4`] function.
    (Join4, <Fut1, Fut2, Fut3, Fut4>),

    /// Future for the [`join5`] function.
    (Join5, <Fut1, Fut2, Fut3, Fut4, Fut5>),
}

/// Joins the result of two futures, waiting for them both to complete.
///
/// This function will return a new future which awaits both futures to
/// complete. The returned future will finish with a tuple of both results.
///
/// Note that this function consumes the passed futures and returns a
/// wrapped version of it.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let pair = future::join(a, b);
///
/// assert_eq!(pair.await, (1, 2));
/// # });
/// ```
pub fn join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2>
where
    Fut1: Future,
    Fut2: Future,
{
    let f = Join::new(future1, future2);
    assert_future::<(Fut1::Output, Fut2::Output), _>(f)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let tuple = future::join3(a, b, c);
///
/// assert_eq!(tuple.await, (1, 2, 3));
/// # });
/// ```
pub fn join3<Fut1, Fut2, Fut3>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
) -> Join3<Fut1, Fut2, Fut3>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
{
    Join3::new(future1, future2, future3)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let d = future::ready(4);
/// let tuple = future::join4(a, b, c, d);
///
/// assert_eq!(tuple.await, (1, 2, 3, 4));
/// # });
/// ```
pub fn join4<Fut1, Fut2, Fut3, Fut4>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
    future4: Fut4,
) -> Join4<Fut1, Fut2, Fut3, Fut4>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
    Fut3: Future,
    Fut4: Future,
{
    Join4::new(future1, future2, future3, future4)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let d = future::ready(4);
/// let e = future::ready(5);
/// let tuple = future::join5(a, b, c, d, e);
///
/// assert_eq!(tuple.await, (1, 2, 3, 4, 5));
/// # });
/// ```
pub fn join5<Fut1, Fut2, Fut3, Fut4, Fut5>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
    future4: Fut4,
    future5: Fut5,
) -> Join5<Fut1, Fut2, Fut3, Fut4, Fut5>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
    Fut4: Future,
    Fut5: Future,
{
    Join5::new(future1, future2, future3, future4, future5)
}
<commit_msg>Remove duplicate trait bound<commit_after>#![allow(non_snake_case)]

use crate::future::{MaybeDone, maybe_done};
use core::fmt;
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::task::{Context, Poll};
use pin_utils::unsafe_pinned;
use super::assert_future;

macro_rules! generate {
    ($(
        $(#[$doc:meta])*
        ($Join:ident, <$($Fut:ident),*>),
    )*) => ($(
        $(#[$doc])*
        #[must_use = "futures do nothing unless you `.await` or poll them"]
        pub struct $Join<$($Fut: Future),*> {
            $($Fut: MaybeDone<$Fut>,)*
        }

        impl<$($Fut),*> fmt::Debug for $Join<$($Fut),*>
        where
            $(
                $Fut: Future + fmt::Debug,
                $Fut::Output: fmt::Debug,
            )*
        {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.debug_struct(stringify!($Join))
                    $(.field(stringify!($Fut), &self.$Fut))*
                    .finish()
            }
        }

        impl<$($Fut: Future),*> $Join<$($Fut),*> {
            fn new($($Fut: $Fut),*) -> $Join<$($Fut),*> {
                $Join {
                    $($Fut: maybe_done($Fut)),*
                }
            }
            $(
                unsafe_pinned!($Fut: MaybeDone<$Fut>);
            )*
        }

        impl<$($Fut: Future),*> Future for $Join<$($Fut),*> {
            type Output = ($($Fut::Output),*);

            fn poll(
                mut self: Pin<&mut Self>, cx: &mut Context<'_>
            ) -> Poll<Self::Output> {
                let mut all_done = true;
                $(
                    all_done &= self.as_mut().$Fut().poll(cx).is_ready();
                )*

                if all_done {
                    Poll::Ready(($(self.as_mut().$Fut().take_output().unwrap()), *))
                } else {
                    Poll::Pending
                }
            }
        }
    )*)
}

generate! {
    /// Future for the [`join`](join()) function.
    (Join, <Fut1, Fut2>),

    /// Future for the [`join3`] function.
    (Join3, <Fut1, Fut2, Fut3>),

    /// Future for the [`join4`] function.
    (Join4, <Fut1, Fut2, Fut3, Fut4>),

    /// Future for the [`join5`] function.
    (Join5, <Fut1, Fut2, Fut3, Fut4, Fut5>),
}

/// Joins the result of two futures, waiting for them both to complete.
///
/// This function will return a new future which awaits both futures to
/// complete. The returned future will finish with a tuple of both results.
///
/// Note that this function consumes the passed futures and returns a
/// wrapped version of it.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let pair = future::join(a, b);
///
/// assert_eq!(pair.await, (1, 2));
/// # });
/// ```
pub fn join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2>
where
    Fut1: Future,
    Fut2: Future,
{
    let f = Join::new(future1, future2);
    assert_future::<(Fut1::Output, Fut2::Output), _>(f)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let tuple = future::join3(a, b, c);
///
/// assert_eq!(tuple.await, (1, 2, 3));
/// # });
/// ```
pub fn join3<Fut1, Fut2, Fut3>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
) -> Join3<Fut1, Fut2, Fut3>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
{
    Join3::new(future1, future2, future3)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let d = future::ready(4);
/// let tuple = future::join4(a, b, c, d);
///
/// assert_eq!(tuple.await, (1, 2, 3, 4));
/// # });
/// ```
pub fn join4<Fut1, Fut2, Fut3, Fut4>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
    future4: Fut4,
) -> Join4<Fut1, Fut2, Fut3, Fut4>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
    Fut4: Future,
{
    Join4::new(future1, future2, future3, future4)
}

/// Same as [`join`](join()), but with more futures.
///
/// # Examples
///
/// ```
/// #![feature(async_await)]
/// # futures::executor::block_on(async {
/// use futures::future;
///
/// let a = future::ready(1);
/// let b = future::ready(2);
/// let c = future::ready(3);
/// let d = future::ready(4);
/// let e = future::ready(5);
/// let tuple = future::join5(a, b, c, d, e);
///
/// assert_eq!(tuple.await, (1, 2, 3, 4, 5));
/// # });
/// ```
pub fn join5<Fut1, Fut2, Fut3, Fut4, Fut5>(
    future1: Fut1,
    future2: Fut2,
    future3: Fut3,
    future4: Fut4,
    future5: Fut5,
) -> Join5<Fut1, Fut2, Fut3, Fut4, Fut5>
where
    Fut1: Future,
    Fut2: Future,
    Fut3: Future,
    Fut4: Future,
    Fut5: Future,
{
    Join5::new(future1, future2, future3, future4, future5)
}
<|endoftext|>


<commit_before>use super::memory;
use std::fmt;
use std::io::{stdin, stdout};
use std::io::Write;
use super::instructions;

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg16 {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    SP = 0b11,

    BC_ALT = 0b100,
    DE_ALT = 0b101,
    HL_ALT = 0b110
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg16qq {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    AF = 0b11,
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg8 {
    A = 0b111,
    B = 0b000,
    C = 0b001,
    D = 0b010,
    E = 0b011,
    H = 0b100,
    L = 0b101
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Port {
    MEMORY = 0x7ffd,
    AY38912_REG14 = 0xfffd,
    AY38912_REG14_W = 0xbffd
}
}

bitflags! {
    pub flags StatusIndicatorFlags: u8 {
        const CARRY_FLAG           = 0b00000001, // C
        const ADD_SUBTRACT_FLAG    = 0b00000010, // N
        const PARITY_OVERFLOW_FLAG = 0b00000100, // P/V
        const HALF_CARRY_FLAG      = 0b00010000, // H
        const ZERO_FLAG            = 0b01000000, // Z
        const SIGN_FLAG            = 0b10000000  // S
    }
}

pub struct Cpu {
    // main register set
    a: u8, f: StatusIndicatorFlags,
    b: u8, c: u8,
    d: u8, e: u8,
    h: u8, l: u8,

    // alternate register set
    a_alt: u8, f_alt: StatusIndicatorFlags,
    b_alt: u8, c_alt: u8,
    d_alt: u8, e_alt: u8,
    h_alt: u8, l_alt: u8,

    // interrupt vector
    i: u8,

    // memory refresh
    r: u8,

    // index register X
    ix: u16,

    // index register Y
    iy: u16,

    // stack pointer
    sp: u16,

    // program counter
    pc: u16,

    // interrupt flip-flops
    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "
                                               ------------
                         ------                | SZ_H_PNC |
                     a:  | {:02X} |             f: | {:08b} |
                         ------                ------------

                         -----------           -----------
                     bc: | {:02X} | {:02X} |   bc_alt: | {:02X} | {:02X} |
                     de: | {:02X} | {:02X} |   de_alt: | {:02X} | {:02X} |
                     hl: | {:02X} | {:02X} |   hl_alt: | {:02X} | {:02X} |
                         -----------           -----------

                         -----------
                     ir: | {:02X} | {:02X} |
                         -----------

                         ----------
                     ix: |  {:04X}  |
                     iy: |  {:04X}  |
                     sp: |  {:04X}  |
                     pc: |  {:04X}  |
                         ----------",
                      self.a,
                      self.f.bits(),
                      self.b, self.c, self.b_alt, self.c_alt,
                      self.d, self.e, self.d_alt, self.e_alt,
                      self.h, self.l, self.h_alt, self.l_alt,
                      self.i, self.r,
                      self.ix,
                      self.iy,
                      self.sp,
                      self.pc)
    }
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            a: 0, f: StatusIndicatorFlags::empty(),
            b: 0, c: 0,
            d: 0, e: 0,
            h: 0, l: 0,
            a_alt: 0, f_alt: StatusIndicatorFlags::empty(),
            b_alt: 0, c_alt: 0,
            d_alt: 0, e_alt: 0,
            h_alt: 0, l_alt: 0,
            i: 0,
            r: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,
            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        let mut debug_on = true;

        loop {
            if debug_on {
                print!("z80> ");
                stdout().flush().unwrap();

                let mut input = String::new();
                stdin().read_line(&mut input).unwrap();
                let input: String = input.trim().into();

                match input.as_ref() {
                    "step" => self.run_instruction(),
                    "regs" => println!("{:?}", self),
                    "run"  => debug_on = false,
                    "exit" => break,
                    _ => println!("Unknown command")
                };
            } else {
                self.run_instruction();
                // Poor man's breakpoint:
                // if self.get_pc() == 0x00f4 { debug_on = true };
            }
        }
    }

    pub fn read_reg8(&self, reg: Reg8) -> u8 {
        match reg {
            Reg8::A => self.a,
            Reg8::B => self.b,
            Reg8::C => self.c,
            Reg8::D => self.d,
            Reg8::E => self.e,
            Reg8::H => self.h,
            Reg8::L => self.l
        }
    }

    pub fn write_reg8(&mut self, reg: Reg8, val: u8) {
        match reg {
            Reg8::A => self.a = val,
            Reg8::B => self.b = val,
            Reg8::C => self.c = val,
            Reg8::D => self.d = val,
            Reg8::E => self.e = val,
            Reg8::H => self.h = val,
            Reg8::L => self.l = val
        }
    }

    pub fn read_reg16(&self, reg: Reg16) -> u16 {
        let value = match reg {
            Reg16::SP => self.sp,
            _ => {
                let (high, low) = match reg {
                    Reg16::BC => (self.b, self.c),
                    Reg16::DE => (self.d, self.e),
                    Reg16::HL => (self.h, self.l),
                    Reg16::BC_ALT => (self.b_alt, self.c_alt),
                    Reg16::DE_ALT => (self.d_alt, self.e_alt),
                    Reg16::HL_ALT => (self.h_alt, self.l_alt),
                    _ => unreachable!()
                };
                (((high as u16) << 8 ) | low as u16)
            }
        };
        value
    }

    pub fn write_reg16(&mut self, reg: Reg16, val: u16) {
        let (high, low) = (((val & 0xFF00) >> 8) as u8, (val & 0x00FF) as u8);
        match reg {
            Reg16::BC => { self.b = high; self.c = low; }
            Reg16::DE => { self.d = high; self.e = low; }
            Reg16::HL => { self.h = high; self.l = low; }
            Reg16::BC_ALT => { self.b_alt = high; self.c_alt = low; }
            Reg16::DE_ALT => { self.d_alt = high; self.e_alt = low; }
            Reg16::HL_ALT => { self.h_alt = high; self.l_alt = low; }
            Reg16::SP => { self.sp = val }
        }
    }

    pub fn read_reg16qq(&self, reg: Reg16qq) -> u16 {
        let (high, low) = match reg {
            Reg16qq::BC => (self.b, self.c),
            Reg16qq::DE => (self.d, self.e),
            Reg16qq::HL => (self.h, self.l),
            Reg16qq::AF => (self.a, self.f.bits() as u8)
        };
        ((high as u16) << 8 ) | low as u16
    }

    pub fn write_reg16qq(&mut self, reg: Reg16qq, val: u16) {
        let (high, low) = (((val & 0xFF00) >> 8) as u8, (val & 0x00FF) as u8);
        match reg {
            Reg16qq::BC => { self.b = high; self.c = low; }
            Reg16qq::DE => { self.d = high; self.e = low; }
            Reg16qq::HL => { self.h = high; self.l = low; }
            Reg16qq::AF => { self.a = high; self.f = StatusIndicatorFlags::from_bits_truncate(low); }
        }
    }

    pub fn inc_pc(&mut self, val: u16) { self.pc += val; }
    pub fn set_pc(&mut self, val: u16) { self.pc = val; }
    pub fn get_pc(&self) -> u16 { self.pc }

    pub fn set_ix(&mut self, val: u16) { self.ix = val; }
    pub fn get_ix(&self) -> u16 { self.ix }
    pub fn set_iy(&mut self, val: u16) { self.iy = val; }
    pub fn get_iy(&self) -> u16 { self.iy }

    pub fn set_iff1(&mut self)   { self.iff1 = true;  }
    pub fn clear_iff1(&mut self) { self.iff1 = false; }
    pub fn set_iff2(&mut self)   { self.iff2 = true;  }
    pub fn clear_iff2(&mut self) { self.iff2 = false; }

    pub fn set_flag(&mut self, flag: StatusIndicatorFlags) { self.f.insert(flag); }
    pub fn clear_flag(&mut self, flag: StatusIndicatorFlags) { self.f.remove(flag); }
    pub fn get_flag(&self, flag: StatusIndicatorFlags) -> bool { self.f.contains(flag) }

    fn run_instruction(&mut self) {
        let instruction = self.read_word(self.pc);

        let instrs = &instructions::INSTR_TABLE[instruction as usize];

        instrs.execute(self);
    }

    pub fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }

    pub fn write_word(&mut self, addr: u16, val: u8) {
        self.memory.write_word(addr, val);
    }

    pub fn read_port(&self, port: Port) -> u8 {
        // TODO
        match port {
            Port::MEMORY => 0x42,
            Port::AY38912_REG14 => 0x42,
            Port::AY38912_REG14_W => unreachable!()
        }
    }

    pub fn write_port(&mut self, port: Port, val: u8) {
        // TODO
        match port {
            Port::MEMORY =>
                match val {
                    0 => self.memory.change_bank(val),
                    _ => ()
                },
            Port::AY38912_REG14 => (),
            Port::AY38912_REG14_W => ()
        }
    }
}

<commit_msg>Add simple mem debug instruction<commit_after>use super::memory;
use std::fmt;
use std::io::{stdin, stdout};
use std::io::Write;
use super::instructions;

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg16 {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    SP = 0b11,

    BC_ALT = 0b100,
    DE_ALT = 0b101,
    HL_ALT = 0b110
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg16qq {
    BC = 0b00,
    DE = 0b01,
    HL = 0b10,
    AF = 0b11,
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Reg8 {
    A = 0b111,
    B = 0b000,
    C = 0b001,
    D = 0b010,
    E = 0b011,
    H = 0b100,
    L = 0b101
}
}

enum_from_primitive! {
#[derive(Debug, Clone, Copy)]
pub enum Port {
    MEMORY = 0x7ffd,
    AY38912_REG14 = 0xfffd,
    AY38912_REG14_W = 0xbffd
}
}

bitflags! {
    pub flags StatusIndicatorFlags: u8 {
        const CARRY_FLAG           = 0b00000001, // C
        const ADD_SUBTRACT_FLAG    = 0b00000010, // N
        const PARITY_OVERFLOW_FLAG = 0b00000100, // P/V
        const HALF_CARRY_FLAG      = 0b00010000, // H
        const ZERO_FLAG            = 0b01000000, // Z
        const SIGN_FLAG            = 0b10000000  // S
    }
}

pub struct Cpu {
    // main register set
    a: u8, f: StatusIndicatorFlags,
    b: u8, c: u8,
    d: u8, e: u8,
    h: u8, l: u8,

    // alternate register set
    a_alt: u8, f_alt: StatusIndicatorFlags,
    b_alt: u8, c_alt: u8,
    d_alt: u8, e_alt: u8,
    h_alt: u8, l_alt: u8,

    // interrupt vector
    i: u8,

    // memory refresh
    r: u8,

    // index register X
    ix: u16,

    // index register Y
    iy: u16,

    // stack pointer
    sp: u16,

    // program counter
    pc: u16,

    // interrupt flip-flops
    iff1: bool,
    iff2: bool,

    memory: memory::Memory
}

impl fmt::Debug for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "
                                               ------------
                         ------                | SZ_H_PNC |
                     a:  | {:02X} |             f: | {:08b} |
                         ------                ------------

                         -----------           -----------
                     bc: | {:02X} | {:02X} |   bc_alt: | {:02X} | {:02X} |
                     de: | {:02X} | {:02X} |   de_alt: | {:02X} | {:02X} |
                     hl: | {:02X} | {:02X} |   hl_alt: | {:02X} | {:02X} |
                         -----------           -----------

                         -----------
                     ir: | {:02X} | {:02X} |
                         -----------

                         ----------
                     ix: |  {:04X}  |
                     iy: |  {:04X}  |
                     sp: |  {:04X}  |
                     pc: |  {:04X}  |
                         ----------",
                      self.a,
                      self.f.bits(),
                      self.b, self.c, self.b_alt, self.c_alt,
                      self.d, self.e, self.d_alt, self.e_alt,
                      self.h, self.l, self.h_alt, self.l_alt,
                      self.i, self.r,
                      self.ix,
                      self.iy,
                      self.sp,
                      self.pc)
    }
}

impl Cpu {
    pub fn new(memory: memory::Memory) -> Cpu {
        Cpu {
            a: 0, f: StatusIndicatorFlags::empty(),
            b: 0, c: 0,
            d: 0, e: 0,
            h: 0, l: 0,
            a_alt: 0, f_alt: StatusIndicatorFlags::empty(),
            b_alt: 0, c_alt: 0,
            d_alt: 0, e_alt: 0,
            h_alt: 0, l_alt: 0,
            i: 0,
            r: 0,
            ix: 0,
            iy: 0,
            sp: 0,
            pc: 0,
            iff1: false,
            iff2: false,

            memory: memory
        }
    }

    pub fn run(&mut self) {
        let mut debug_on = true;

        loop {
            if debug_on {
                print!("z80> ");
                stdout().flush().unwrap();

                let mut input = String::new();
                stdin().read_line(&mut input).unwrap();
                let input: String = input.trim().into();

                let cmd: Vec<&str> = input.split(" ").collect();

                match cmd[0].as_ref() {
                    "step" => self.run_instruction(),
                    "regs" => println!("{:?}", self),
                    "run"  => debug_on = false,
                    "exit" => break,
                    "mem"  => println!("{:#04X}", self.read_word(u16::from_str_radix(cmd[1], 16).unwrap())),
                    _ => println!("Unknown command")
                };
            } else {
                self.run_instruction();
                // Poor man's breakpoint:
                // if self.get_pc() == 0x00f4 { debug_on = true };
            }
        }
    }

    pub fn read_reg8(&self, reg: Reg8) -> u8 {
        match reg {
            Reg8::A => self.a,
            Reg8::B => self.b,
            Reg8::C => self.c,
            Reg8::D => self.d,
            Reg8::E => self.e,
            Reg8::H => self.h,
            Reg8::L => self.l
        }
    }

    pub fn write_reg8(&mut self, reg: Reg8, val: u8) {
        match reg {
            Reg8::A => self.a = val,
            Reg8::B => self.b = val,
            Reg8::C => self.c = val,
            Reg8::D => self.d = val,
            Reg8::E => self.e = val,
            Reg8::H => self.h = val,
            Reg8::L => self.l = val
        }
    }

    pub fn read_reg16(&self, reg: Reg16) -> u16 {
        let value = match reg {
            Reg16::SP => self.sp,
            _ => {
                let (high, low) = match reg {
                    Reg16::BC => (self.b, self.c),
                    Reg16::DE => (self.d, self.e),
                    Reg16::HL => (self.h, self.l),
                    Reg16::BC_ALT => (self.b_alt, self.c_alt),
                    Reg16::DE_ALT => (self.d_alt, self.e_alt),
                    Reg16::HL_ALT => (self.h_alt, self.l_alt),
                    _ => unreachable!()
                };
                (((high as u16) << 8 ) | low as u16)
            }
        };
        value
    }

    pub fn write_reg16(&mut self, reg: Reg16, val: u16) {
        let (high, low) = (((val & 0xFF00) >> 8) as u8, (val & 0x00FF) as u8);
        match reg {
            Reg16::BC => { self.b = high; self.c = low; }
            Reg16::DE => { self.d = high; self.e = low; }
            Reg16::HL => { self.h = high; self.l = low; }
            Reg16::BC_ALT => { self.b_alt = high; self.c_alt = low; }
            Reg16::DE_ALT => { self.d_alt = high; self.e_alt = low; }
            Reg16::HL_ALT => { self.h_alt = high; self.l_alt = low; }
            Reg16::SP => { self.sp = val }
        }
    }

    pub fn read_reg16qq(&self, reg: Reg16qq) -> u16 {
        let (high, low) = match reg {
            Reg16qq::BC => (self.b, self.c),
            Reg16qq::DE => (self.d, self.e),
            Reg16qq::HL => (self.h, self.l),
            Reg16qq::AF => (self.a, self.f.bits() as u8)
        };
        ((high as u16) << 8 ) | low as u16
    }

    pub fn write_reg16qq(&mut self, reg: Reg16qq, val: u16) {
        let (high, low) = (((val & 0xFF00) >> 8) as u8, (val & 0x00FF) as u8);
        match reg {
            Reg16qq::BC => { self.b = high; self.c = low; }
            Reg16qq::DE => { self.d = high; self.e = low; }
            Reg16qq::HL => { self.h = high; self.l = low; }
            Reg16qq::AF => { self.a = high; self.f = StatusIndicatorFlags::from_bits_truncate(low); }
        }
    }

    pub fn inc_pc(&mut self, val: u16) { self.pc += val; }
    pub fn set_pc(&mut self, val: u16) { self.pc = val; }
    pub fn get_pc(&self) -> u16 { self.pc }

    pub fn set_ix(&mut self, val: u16) { self.ix = val; }
    pub fn get_ix(&self) -> u16 { self.ix }
    pub fn set_iy(&mut self, val: u16) { self.iy = val; }
    pub fn get_iy(&self) -> u16 { self.iy }

    pub fn set_iff1(&mut self)   { self.iff1 = true;  }
    pub fn clear_iff1(&mut self) { self.iff1 = false; }
    pub fn set_iff2(&mut self)   { self.iff2 = true;  }
    pub fn clear_iff2(&mut self) { self.iff2 = false; }

    pub fn set_flag(&mut self, flag: StatusIndicatorFlags) { self.f.insert(flag); }
    pub fn clear_flag(&mut self, flag: StatusIndicatorFlags) { self.f.remove(flag); }
    pub fn get_flag(&self, flag: StatusIndicatorFlags) -> bool { self.f.contains(flag) }

    fn run_instruction(&mut self) {
        let instruction = self.read_word(self.pc);

        let instrs = &instructions::INSTR_TABLE[instruction as usize];

        instrs.execute(self);
    }

    pub fn read_word(&self, addr: u16) -> u8 {
        self.memory.read_word(addr)
    }

    pub fn write_word(&mut self, addr: u16, val: u8) {
        self.memory.write_word(addr, val);
    }

    pub fn read_port(&self, port: Port) -> u8 {
        // TODO
        match port {
            Port::MEMORY => 0x42,
            Port::AY38912_REG14 => 0x42,
            Port::AY38912_REG14_W => unreachable!()
        }
    }

    pub fn write_port(&mut self, port: Port, val: u8) {
        // TODO
        match port {
            Port::MEMORY =>
                match val {
                    0 => self.memory.change_bank(val),
                    _ => ()
                },
            Port::AY38912_REG14 => (),
            Port::AY38912_REG14_W => ()
        }
    }
}

<|endoftext|>


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

extern crate maud;
extern crate iron;
extern crate router;
extern crate logger;
extern crate pulldown_cmark;
extern crate git_appraise;
extern crate persistent;
extern crate typemap;
extern crate chrono;
extern crate maud_pulldown_cmark;

use maud::PreEscaped;
use std::env;
use iron::prelude::*;
use iron::status;
use router::*;
use logger::*;
use iron::mime::Mime;
use git_appraise::{ Oid, Repository, Review };
use persistent::{ Read };
use typemap::Key;
use maud_pulldown_cmark::Markdown;

fn style() -> String {
  format!("
    html * {{
      color-profile: sRGB;
      rendering-intent: auto;
    }}

    body {{
      background-color: {base03};
      color: {base0};
    }}

    h1, h2, h3, h4, h5, h6 {{
      color: {base1};
      border-color: {base0};
    }}

    body {{
      font-family: \"Raleway\", \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;
      margin: 20px auto;
      max-width: 650px;
      line-height: 1.4;
      font-size: 18px;
      padding: 0 10px;
    }}

    h1,h2,h3 {{
      font-family: \"Lucida Console\", Monaco, monospace;
      line-height: 1.2;
    }}

    a {{
      color: {blue};
      text-decoration: none;
      cursor: pointer;
    }}

    a:hover {{
      color: {lightblue}
    }}
  ",
    base03 = "#002b36",
    // base02 = "#073642",
    // base01 = "#586e75",
    // base00 = "#657b83",
    base0 = "#839496",
    base1 = "#93a1a1",
    // base2 = "#eee8d5",
    // base3 = "#fdf6e3",
    // yellow = "#b58900",
    // orange = "#cb4b16",
    // red = "#dc322f",
    // magenta = "#d33682",
    // violet = "#6c71c4",
    blue = "#268bd2",
    // cyan = "#2aa198",
    // green = "#859900",
    lightblue = "#3797db"
  )
}

fn get_reviews(repo: &Repository) -> Vec<git_appraise::Result<(Oid, Review)>> {
  repo.reviews().unwrap().map(|id| repo.review(id).map(|rev| (id, rev))).collect()
}

fn get_review(repo: &Repository, id: &str) -> Review {
  let id = Oid::from_str(id).unwrap();
  repo.review(id).unwrap()
}

fn render_reviews(reviews: Vec<Result<(Oid, Review), git_appraise::Error>>) -> String {
  let mut buffer = String::new();
  html!(buffer, {
    head {
      style type="text/css" {
        $PreEscaped(style())
      }
    }
    body {
      ol {
        #for rev in &reviews {
          #if let Some(&(ref id, ref review)) = rev.as_ref().ok() {
            li {
              a href={ "/" $id } $id
              " -> "
              $review.description().unwrap()
            }
          }
          #if let Some(ref err) = rev.as_ref().err() {
            li {
              $err
            }
          }
        }
      }
    }
  }).unwrap();
  buffer
}

fn render_review(review: Review) -> String {
  let mut buffer = String::new();
  html!(buffer, {
    head {
      style type="text/css" {
        $PreEscaped(style())
      }
    }
    body {
      ul {
        #if let Some(requester) = review.requester() {
          li { "Requester: " $requester }
        }
        #if let Some(timestamp) = review.timestamp() {
          li { "Timestamp: " $(chrono::naive::datetime::NaiveDateTime::from_timestamp(timestamp.seconds(), 0)) }
        }
        #if let (Some(review_ref), Some(target_ref)) = (review.review_ref(), review.target_ref()) {
          li { "Proposed merge: " $review_ref " -> " $target_ref }
        }
        #if let Some(reviewers) = review.reviewers() {
          li { "Reviewers:"
            ul {
              #for reviewer in reviewers {
                li $reviewer
              }
            }
          }
        }
        #if let Some(ref description) = review.description() {
          li {
            "Description: "
            $(Markdown::FromString(description))
          }
        }
      }
    }
  }).unwrap();
  buffer
}

pub fn result(buffer: String) -> IronResult<Response> {
  Ok(Response::with(("text/html".parse::<Mime>().unwrap(), status::Ok, buffer)))
}

fn reviews_handler(req: &mut iron::request::Request) -> IronResult<Response> {
  let path = req.get::<Read<RepositoryPath>>().unwrap();
  let repo = Repository::open(&*path).unwrap();
  let reviews = get_reviews(&repo);
  let buffer = render_reviews(reviews);
  result(buffer)
}

fn review_handler(req: &mut iron::request::Request) -> IronResult<Response> {
  let path = req.get::<Read<RepositoryPath>>().unwrap();
  let repo = Repository::open(&*path).unwrap();
  let review = get_review(&repo, req.extensions.get::<Router>().unwrap().find("query").unwrap());
  let buffer = render_review(review);
  result(buffer)
}

#[derive(Copy, Clone)]
struct RepositoryPath;
impl Key for RepositoryPath { type Value = String; }

fn main() {
  let path = env::args().nth(1).unwrap();

  let mut router = Router::new();
  router.get("/", reviews_handler);

  router.get("/:query", review_handler);

  let (logger_before, logger_after) = Logger::new(None);

  let mut chain = Chain::new(router);

  chain.link(Read::<RepositoryPath>::both(path));
  chain.link_before(logger_before);
  chain.link_after(logger_after);

  Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>Render CI status for a review<commit_after>#![feature(plugin)]
#![plugin(maud_macros)]

extern crate maud;
extern crate iron;
extern crate router;
extern crate logger;
extern crate pulldown_cmark;
extern crate git_appraise;
extern crate persistent;
extern crate typemap;
extern crate chrono;
extern crate maud_pulldown_cmark;

use maud::PreEscaped;
use std::env;
use iron::prelude::*;
use iron::status;
use router::*;
use logger::*;
use iron::mime::Mime;
use git_appraise::{ Oid, Repository, Review, CIStatus, Status };
use persistent::{ Read };
use typemap::Key;
use maud_pulldown_cmark::Markdown;

fn style() -> String {
  format!("
    html * {{
      color-profile: sRGB;
      rendering-intent: auto;
    }}

    body {{
      background-color: {base03};
      color: {base0};
    }}

    h1, h2, h3, h4, h5, h6 {{
      color: {base1};
      border-color: {base0};
    }}

    body {{
      font-family: \"Raleway\", \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;
      margin: 20px auto;
      max-width: 650px;
      line-height: 1.4;
      font-size: 18px;
      padding: 0 10px;
    }}

    h1,h2,h3 {{
      font-family: \"Lucida Console\", Monaco, monospace;
      line-height: 1.2;
    }}

    a {{
      color: {blue};
      text-decoration: none;
      cursor: pointer;
    }}

    a:hover {{
      color: {lightblue}
    }}
  ",
    base03 = "#002b36",
    // base02 = "#073642",
    // base01 = "#586e75",
    // base00 = "#657b83",
    base0 = "#839496",
    base1 = "#93a1a1",
    // base2 = "#eee8d5",
    // base3 = "#fdf6e3",
    // yellow = "#b58900",
    // orange = "#cb4b16",
    // red = "#dc322f",
    // magenta = "#d33682",
    // violet = "#6c71c4",
    blue = "#268bd2",
    // cyan = "#2aa198",
    // green = "#859900",
    lightblue = "#3797db"
  )
}

fn get_reviews(repo: &Repository) -> Vec<git_appraise::Result<(Oid, Review)>> {
  repo.reviews().unwrap().map(|id| repo.review(id).map(|rev| (id, rev))).collect()
}

fn get_ci_statuses_for(repo: &Repository, id: Oid) -> Vec<CIStatus> {
  repo.ci_statuses_for(id).unwrap().into_iter().filter_map(|s| s.ok()).collect()
}

fn get_review(repo: &Repository, id: Oid) -> Review {
  repo.review(id).unwrap()
}

fn render_reviews(reviews: Vec<Result<(Oid, Review), git_appraise::Error>>) -> String {
  let mut buffer = String::new();
  html!(buffer, {
    head {
      style type="text/css" {
        $PreEscaped(style())
      }
    }
    body {
      ol {
        #for rev in &reviews {
          #if let Some(&(ref id, ref review)) = rev.as_ref().ok() {
            li {
              a href={ "/" $id } $id
              " -> "
              $review.description().unwrap()
            }
          }
          #if let Some(ref err) = rev.as_ref().err() {
            li {
              $err
            }
          }
        }
      }
    }
  }).unwrap();
  buffer
}

fn render_review(review: Review, statuses: Vec<CIStatus>) -> String {
  let mut buffer = String::new();
  html!(buffer, {
    head {
      style type="text/css" {
        $PreEscaped(style())
      }
    }
    body {
      ul {
        #if let Some(requester) = review.requester() {
          li { "Requester: " $requester }
        }
        #if let Some(timestamp) = review.timestamp() {
          li { "Timestamp: " $(chrono::naive::datetime::NaiveDateTime::from_timestamp(timestamp.seconds(), 0)) }
        }
        #if let (Some(review_ref), Some(target_ref)) = (review.review_ref(), review.target_ref()) {
          li { "Proposed merge: " $review_ref " -> " $target_ref }
        }
        #if let Some(reviewers) = review.reviewers() {
          li { "Reviewers:"
            ul {
              #for reviewer in reviewers {
                li $reviewer
              }
            }
          }
        }
        #if let Some(ref description) = review.description() {
          li {
            "Description: "
            $(Markdown::FromString(description))
          }
        }
        #if statuses.len() > 0 {
          li {
            "CI Statuses: "
            ol {
              #for status in &statuses {
                li {
                  #if let Some(url) = status.url() {
                    a href={ $url } $status.agent().unwrap_or("<Unknown agent>")
                  }
                  #if status.url().is_none() {
                    $status.agent().unwrap_or("<Unknown agent>")
                  }
                  ": "
                  $status.status().map(|s| match s { Status::Success => "success", Status::Failure => "failure" }).unwrap_or("null")
                }
              }
            }
          }
        }
      }
    }
  }).unwrap();
  buffer
}

pub fn result(buffer: String) -> IronResult<Response> {
  Ok(Response::with(("text/html".parse::<Mime>().unwrap(), status::Ok, buffer)))
}

fn reviews_handler(req: &mut iron::request::Request) -> IronResult<Response> {
  let path = req.get::<Read<RepositoryPath>>().unwrap();
  let repo = Repository::open(&*path).unwrap();
  let reviews = get_reviews(&repo);
  let buffer = render_reviews(reviews);
  result(buffer)
}

fn review_handler(req: &mut iron::request::Request) -> IronResult<Response> {
  let path = req.get::<Read<RepositoryPath>>().unwrap();
  let repo = Repository::open(&*path).unwrap();
  let id = Oid::from_str(req.extensions.get::<Router>().unwrap().find("query").unwrap()).unwrap();
  let review = get_review(&repo, id);
  let statuses = get_ci_statuses_for(&repo, id);
  let buffer = render_review(review, statuses);
  result(buffer)
}

#[derive(Copy, Clone)]
struct RepositoryPath;
impl Key for RepositoryPath { type Value = String; }

fn main() {
  let path = env::args().nth(1).unwrap();

  let mut router = Router::new();
  router.get("/", reviews_handler);
  router.get("/:query", review_handler);

  let (logger_before, logger_after) = Logger::new(None);

  let mut chain = Chain::new(router);

  chain.link(Read::<RepositoryPath>::both(path));
  chain.link_before(logger_before);
  chain.link_after(logger_after);

  Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>


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

pub type AttrMap = HashMap<String, String>;

pub struct Node {
    pub children: Vec<Node>,
    node_type: NodeType
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.node_type)
    }
}

enum NodeType {
    Text(String),
    Element(ElementData),
    Comment(String)
}

impl fmt::Display for NodeType {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			NodeType::Text(ref s) => write!(f, "{}", s),
			NodeType::Element(ref e) => write!(f, "{}", e),
			NodeType::Comment(ref c) => write!(f, "{}", c)
		}
	}
}

struct ElementData {
    tag_name: String,
    attributes: AttrMap
}

impl fmt::Display for ElementData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut attributes_string = String::new();

        for (attr, value) in self.attributes.iter() {
            attributes_string.push_str(&format!(" {}=\"{}\"", attr, value));
        }
        write!(f, "<{}{}>", self.tag_name, attributes_string)
    }
}

pub fn text_node(data: String) -> Node {
    Node { children: Vec::new(), node_type: NodeType::Text(data) }
}

pub fn element_node(name: String, attrs: AttrMap, children: Vec<Node>) -> Node {
    Node {
        children: children,
        node_type: NodeType::Element( ElementData {
            tag_name: name,
            attributes: attrs,
        })
    }
}

pub fn comment_node(data: String) -> Node {
    Node { children: Vec::new(), node_type: NodeType::Comment(data) }
}

pub fn pretty_print(n: Node, indent_size: usize) {
    let indent = (0..indent_size).map(|_| " ").collect::<String>();

    match n.node_type {
        NodeType::Element(ref e) => println!("{}{}", indent, e),
        NodeType::Text(ref t) => println!("{}{}", indent, t),
        NodeType::Comment(ref c) => println!("{}<!--{}-->", indent, c),
    }

    for child in n.children {
        pretty_print(child, indent_size + 2);
    }

    match n.node_type {
        NodeType::Element(ref e) => println!("{}</{}>", indent, e.tag_name),
        _ => {}
    }
}<commit_msg>fix formatting<commit_after>use std::collections::HashMap;
use std::fmt;

pub type AttrMap = HashMap<String, String>;

pub struct Node {
    pub children: Vec<Node>,
    node_type: NodeType
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.node_type)
    }
}

enum NodeType {
    Text(String),
    Element(ElementData),
    Comment(String)
}

impl fmt::Display for NodeType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            NodeType::Text(ref s) => write!(f, "{}", s),
            NodeType::Element(ref e) => write!(f, "{}", e),
            NodeType::Comment(ref c) => write!(f, "{}", c)
        }
    }
}

struct ElementData {
    tag_name: String,
    attributes: AttrMap
}

impl fmt::Display for ElementData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut attributes_string = String::new();

        for (attr, value) in self.attributes.iter() {
            attributes_string.push_str(&format!(" {}=\"{}\"", attr, value));
        }
        write!(f, "<{}{}>", self.tag_name, attributes_string)
    }
}

pub fn text_node(data: String) -> Node {
    Node { children: Vec::new(), node_type: NodeType::Text(data) }
}

pub fn element_node(name: String, attrs: AttrMap, children: Vec<Node>) -> Node {
    Node {
        children: children,
        node_type: NodeType::Element( ElementData {
            tag_name: name,
            attributes: attrs,
        })
    }
}

pub fn comment_node(data: String) -> Node {
    Node { children: Vec::new(), node_type: NodeType::Comment(data) }
}

pub fn pretty_print(n: Node, indent_size: usize) {
    let indent = (0..indent_size).map(|_| " ").collect::<String>();

    match n.node_type {
        NodeType::Element(ref e) => println!("{}{}", indent, e),
        NodeType::Text(ref t) => println!("{}{}", indent, t),
        NodeType::Comment(ref c) => println!("{}<!--{}-->", indent, c),
    }

    for child in n.children {
        pretty_print(child, indent_size + 2);
    }

    match n.node_type {
        NodeType::Element(ref e) => println!("{}</{}>", indent, e.tag_name),
        _ => {}
    }
}<|endoftext|>


<commit_before>use std::os;
use std::io;
use std::path;
use beta::Beta;

pub mod beta;
pub mod mem;

fn load(filename: ~str) -> ~[u8] {
	let read_result: Result<@Reader, ~str>;
	read_result = io::file_reader(~path::Path(filename));

	if read_result.is_ok() {
		let reader = read_result.unwrap();
		return reader.read_whole_stream();
	}

	println(fmt!("Error reading file: %?", read_result.unwrap_err()));
	return ~[];
}

fn main() {
	let args : ~[~str] = os::args();

	if args.len() == 2 {
		// make a beta
		let mut b = Beta::new(4*1024);

		// get user file
		let filename = args[1];
		let filedata = load(filename);

		// put user data in beta
		// beta is big endian, file is little endian
		for i in range(0, filedata.len()) {
			let pos = i/4*4 + (3-i%4);
			b.mem.write(pos as u32, filedata[i]);
		}

		// start
		b.reset();

		let mut count = 0;
		while count < 1000 {
			b.tick();
			count += 1;
		}
	} else {
		println("usage: emu <input file>");
	}
}
<commit_msg>CLI arguments via extra::getopts.<commit_after>extern mod extra;

use std::path;
use std::io;
use std::os;
use extra::getopts;

use beta::Beta;

pub mod beta;
pub mod mem;

fn load(filename: &str) -> ~[u8] {
	let read_result: Result<@Reader, ~str>;
	read_result = io::file_reader(~path::Path(filename));

	if read_result.is_ok() {
		let reader = read_result.unwrap();
		return reader.read_whole_stream();
	}

	println(fmt!("Error reading file: %?", read_result.unwrap_err()));
	return ~[];
}

fn do_work(inp: &str, out: Option<~str>) {
	println(inp);

	/*match out {
		None => { println("No Output"); }
		Some(x) => {
		}
	}*/

	// get user file
	let filedata = load(inp);

	// make a beta
	let mut b = Beta::new(4*1024);

	// put user data in beta
	// beta is big endian, file is little endian
	for i in range(0, filedata.len()) {
		let pos = i/4*4 + (3-i%4);
		b.mem.write(pos as u32, filedata[i]);
	}

	// start
	b.reset();

	let mut count = 0;
	while count < 1000 {
		b.tick();
		count += 1;
	}
}

fn print_usage(program: &str, _opts: &[getopts::Opt]) {
	println(fmt!("Usage: %s [options]", program));
	println("-o\t\tOutput");
	println("-h --help\tUsage");
}

fn main() {
	let args = os::args();

	let program = args[0].clone();

	let opts = ~[
		getopts::optopt("o"),
		getopts::optflag("h"),
		getopts::optflag("help")
	];

	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { fail!(f.to_err_msg()) }
	};

	if matches.opt_present("h") || matches.opt_present("help") {
		print_usage(program, opts);
		return;
	}

	let output = matches.opt_str("o");
	let input: &str = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		print_usage(program, opts);
		return;
	};

	do_work(input, output);
}
<|endoftext|>


<commit_before>

use chrono::*;
use std::fmt;
use timeclock::timeentry::TimeEntry;

#[derive(Clone,Debug)]
pub struct DateRecord {
    date_: Date<FixedOffset>,
    duration: f64,
    memo_: String,
}

impl DateRecord {
    pub fn from_time_entries(start: &TimeEntry, end: &TimeEntry) -> DateRecord {
        let mut dr = DateRecord {
            date_: start.time.date(),
            duration: (end.time - start.time).num_seconds() as f64,
            memo_: String::new(),
        };
        dr.append_memo(&start.memo);
        dr.append_memo(&end.memo);
        return dr;
    }

    /// Get the duration, expressed in seconds
    pub fn seconds(&self) -> f64 {
        self.duration
    }

    #[allow(dead_code)]
    /// Get the duration, expressed in minutes
    pub fn minutes(&self) -> f64 {
        self.duration / 60.0
    }

    /// Get the duration, expressed in hours
    pub fn hours(&self) -> f64 {
        self.duration / 3600.0
    }

    pub fn date(&self) -> Date<FixedOffset> {
        self.date_
    }

    pub fn add_seconds(&mut self, secs: f64) {
        self.duration += secs;
    }

    /// Returns the memo
    pub fn memo(&self) -> &str {
        &self.memo_
    }

    /// Append &str to the memo
    pub fn append_memo(&mut self, memo: &str) {
        if !self.memo_.is_empty() && !memo.is_empty() {
            self.memo_.push_str(", ");
            self.memo_.push_str(memo);
        } else if self.memo_.is_empty() {
            self.memo_.push_str(memo);
        }
    }
}

impl fmt::Display for DateRecord {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {:.2} {}", self.date(), self.hours(), self.memo())
    }
}
<commit_msg>unittests for DateRecord<commit_after>

use chrono::*;
use std::fmt;
use timeclock::timeentry::TimeEntry;

#[derive(Clone,Debug)]
pub struct DateRecord {
    date_: Date<FixedOffset>,
    duration: f64,
    memo_: String,
}

impl DateRecord {
    pub fn from_time_entries(start: &TimeEntry, end: &TimeEntry) -> DateRecord {
        let mut dr = DateRecord {
            date_: start.time.date(),
            duration: (end.time - start.time).num_seconds() as f64,
            memo_: String::new(),
        };
        dr.append_memo(&start.memo);
        dr.append_memo(&end.memo);
        return dr;
    }

    #[allow(dead_code)]
    /// Construct a DateRecord from it's constituent parts
    pub fn from_parts(date: Date<FixedOffset>, dur: f64, memo: &str) -> Self {
        DateRecord {
            date_: date,
            duration: dur,
            memo_: memo.to_owned(),
        }
    }

    /// Get the duration, expressed in seconds
    pub fn seconds(&self) -> f64 {
        self.duration
    }

    #[allow(dead_code)]
    /// Get the duration, expressed in minutes
    pub fn minutes(&self) -> f64 {
        self.duration / 60.0
    }

    /// Get the duration, expressed in hours
    pub fn hours(&self) -> f64 {
        self.duration / 3600.0
    }

    pub fn date(&self) -> Date<FixedOffset> {
        self.date_
    }

    pub fn add_seconds(&mut self, secs: f64) {
        self.duration += secs;
    }

    /// Returns the memo
    pub fn memo(&self) -> &str {
        &self.memo_
    }

    /// Append &str to the memo
    pub fn append_memo(&mut self, memo: &str) {
        if !self.memo_.is_empty() && !memo.is_empty() {
            self.memo_.push_str(", ");
            self.memo_.push_str(memo);
        } else if self.memo_.is_empty() {
            self.memo_.push_str(memo);
        }
    }
}

impl fmt::Display for DateRecord {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {:.2} {}", self.date(), self.hours(), self.memo())
    }
}

#[cfg(test)]
mod tests {
    use chrono::*;
    use super::*;

    fn daterecord_helper() -> DateRecord {
        let x = NaiveDate::parse_from_str("2017-01-07", "%F").unwrap();
        let y = FixedOffset::west(6 * 3600).from_local_date(&x).unwrap();
        DateRecord::from_parts(y, 4321.098765, "Test")
    }

    #[test]
    fn duration_methods_test() {
        let mut dr = daterecord_helper();
        // check math
        assert!(dr.seconds() == 4321.098765);
        assert!(dr.minutes() == 72.01831274999999);
        assert!(dr.hours() == 1.2003052125);
        // check that addition works
        dr.add_seconds(1357.246);
        assert!(dr.seconds() == 5678.344765);
    }

    #[test]
    fn memo_methods_test() {
        let mut dr = daterecord_helper();
        assert!(dr.memo() == "Test");
        // append empty str
        dr.append_memo("");
        assert!(dr.memo() == "Test");
        // append actual str
        dr.append_memo("success!");
        assert!(dr.memo() == "Test, success!");
    }
}<|endoftext|>


<commit_before>use std::{
    convert::TryInto,
    iter::FromIterator,
    num::TryFromIntError,
};

use serde::{
    Deserialize,
    Serialize,
};

use thiserror::Error;

use rnc_core::{
    urs,
    urs_taxid,
};

use crate::sequences::{
    accession::{
        AccessionVec,
        CrossReference,
        RawAccession,
        ReferenceVec,
    },
    basic::Basic,
    crs::CrsVec,
    feedback::FeedbackVec,
    go_annotation::GoAnnotation,
    interacting_protein::InteractingProtein,
    interacting_rna::InteractingRna,
    orf::OrfVec,
    precompute::PrecomputeSummary,
    qa_status::QaStatus,
    r2dt::R2dt,
    raw::Raw,
    rfam_hit::RfamHitVec,
    so_tree,
};

#[derive(Error, Debug)]
pub enum NormalizationError {
    #[error("Could not parse {0}")]
    UrsParsingError(#[from] urs::Error),

    #[error("Could not parse {0}")]
    UrsTaxidParsingError(#[from] urs_taxid::Error),

    #[error("Could not convert {0} to urs number")]
    UrsNumberError(#[from] TryFromIntError),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Normalized {
    urs: String,
    taxid: usize,
    short_urs: String,
    deleted: String,
    qa_status: QaStatus,
    secondary: Option<R2dt>,
    cross_references: Vec<CrossReference>,
    crs: CrsVec,
    overlaps: FeedbackVec,
    go_annotations: Vec<GoAnnotation>,
    interacting_proteins: Vec<InteractingProtein>,
    interacting_rnas: Vec<InteractingRna>,
    so_rna_type_tree: so_tree::SoTree,

    #[serde(flatten)]
    orfs: OrfVec,

    #[serde(flatten)]
    pre_summary: PrecomputeSummary,

    #[serde(flatten)]
    basic: Basic,

    #[serde(flatten)]
    accessions: AccessionVec,

    #[serde(flatten)]
    references: ReferenceVec,

    #[serde(flatten)]
    rfam_hits: RfamHitVec,
    /* #[serde(flatten)]
     * dates: Dates, */
}

impl Normalized {
    pub fn new(raw: Raw, accessions: Vec<RawAccession>) -> Result<Self, NormalizationError> {
        let base = raw.base().clone();

        let urs_taxid = base.urs_taxid.to_owned();
        assert!(
            urs_taxid == accessions[0].urs_taxid,
            "Accession urs {} and base urs {} disagree for id {}",
            accessions[0].urs_taxid,
            urs_taxid,
            base.id
        );
        let parsed: urs_taxid::UrsTaxid = urs_taxid.parse()?;
        let references = ReferenceVec::from_iter(accessions.clone());

        Ok(Self {
            urs: parsed.urs().to_string(),
            taxid: parsed.taxid().try_into()?,
            short_urs: parsed.short(),
            deleted: String::from("N"),
            so_rna_type_tree: raw.so_tree().to_owned(),
            pre_summary: raw.precompute().into(),
            basic: base,
            qa_status: raw.qa_status().to_owned(),
            secondary: raw.r2dt().to_owned(),
            accessions: AccessionVec::from_iter(accessions.clone()),
            cross_references: accessions.into_iter().map(CrossReference::from).collect(),
            crs: raw.crs().to_owned().into_iter().collect(),
            overlaps: raw.feedback().to_owned().into_iter().collect(),
            go_annotations: raw.go_annotations().to_vec(),
            interacting_proteins: raw.interacting_proteins().to_vec(),
            interacting_rnas: raw.interacting_rnas().to_vec(),
            references,
            rfam_hits: raw.rfam_hits().to_owned().into_iter().collect(),
            orfs: raw.orfs().to_vec().into_iter().collect(),
        })
    }

    pub fn id(&self) -> &usize {
        &self.basic.id
    }

    pub fn urs_taxid(&self) -> &str {
        &self.basic.urs_taxid()
    }

    pub fn cross_references(&self) -> &Vec<CrossReference> {
        &self.cross_references
    }

    pub fn description(&self) -> &str {
        self.pre_summary.description()
    }
}
<commit_msg>Add entry type to normalized sequences<commit_after>use std::{
    convert::TryInto,
    iter::FromIterator,
    num::TryFromIntError,
};

use serde::{
    Deserialize,
    Serialize,
};

use thiserror::Error;

use rnc_core::{
    urs,
    urs_taxid,
};

use crate::sequences::{
    accession::{
        AccessionVec,
        CrossReference,
        RawAccession,
        ReferenceVec,
    },
    basic::Basic,
    crs::CrsVec,
    feedback::FeedbackVec,
    go_annotation::GoAnnotation,
    interacting_protein::InteractingProtein,
    interacting_rna::InteractingRna,
    orf::OrfVec,
    precompute::PrecomputeSummary,
    qa_status::QaStatus,
    r2dt::R2dt,
    raw::Raw,
    rfam_hit::RfamHitVec,
    so_tree,
};

#[derive(Error, Debug)]
pub enum NormalizationError {
    #[error("Could not parse {0}")]
    UrsParsingError(#[from] urs::Error),

    #[error("Could not parse {0}")]
    UrsTaxidParsingError(#[from] urs_taxid::Error),

    #[error("Could not convert {0} to urs number")]
    UrsNumberError(#[from] TryFromIntError),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Normalized {
    urs: String,
    taxid: usize,
    short_urs: String,
    entry_type: String,
    deleted: String,
    qa_status: QaStatus,
    secondary: Option<R2dt>,
    cross_references: Vec<CrossReference>,
    crs: CrsVec,
    overlaps: FeedbackVec,
    go_annotations: Vec<GoAnnotation>,
    interacting_proteins: Vec<InteractingProtein>,
    interacting_rnas: Vec<InteractingRna>,
    so_rna_type_tree: so_tree::SoTree,

    #[serde(flatten)]
    orfs: OrfVec,

    #[serde(flatten)]
    pre_summary: PrecomputeSummary,

    #[serde(flatten)]
    basic: Basic,

    #[serde(flatten)]
    accessions: AccessionVec,

    #[serde(flatten)]
    references: ReferenceVec,

    #[serde(flatten)]
    rfam_hits: RfamHitVec,
    /* #[serde(flatten)]
     * dates: Dates, */
}

impl Normalized {
    pub fn new(raw: Raw, accessions: Vec<RawAccession>) -> Result<Self, NormalizationError> {
        let base = raw.base().clone();

        let urs_taxid = base.urs_taxid.to_owned();
        assert!(
            urs_taxid == accessions[0].urs_taxid,
            "Accession urs {} and base urs {} disagree for id {}",
            accessions[0].urs_taxid,
            urs_taxid,
            base.id
        );
        let parsed: urs_taxid::UrsTaxid = urs_taxid.parse()?;
        let references = ReferenceVec::from_iter(accessions.clone());

        Ok(Self {
            urs: parsed.urs().to_string(),
            taxid: parsed.taxid().try_into()?,
            short_urs: parsed.short(),
            entry_type: "Sequence".to_string(),
            deleted: String::from("N"),
            so_rna_type_tree: raw.so_tree().to_owned(),
            pre_summary: raw.precompute().into(),
            basic: base,
            qa_status: raw.qa_status().to_owned(),
            secondary: raw.r2dt().to_owned(),
            accessions: AccessionVec::from_iter(accessions.clone()),
            cross_references: accessions.into_iter().map(CrossReference::from).collect(),
            crs: raw.crs().to_owned().into_iter().collect(),
            overlaps: raw.feedback().to_owned().into_iter().collect(),
            go_annotations: raw.go_annotations().to_vec(),
            interacting_proteins: raw.interacting_proteins().to_vec(),
            interacting_rnas: raw.interacting_rnas().to_vec(),
            references,
            rfam_hits: raw.rfam_hits().to_owned().into_iter().collect(),
            orfs: raw.orfs().to_vec().into_iter().collect(),
        })
    }

    pub fn id(&self) -> &usize {
        &self.basic.id
    }

    pub fn urs_taxid(&self) -> &str {
        &self.basic.urs_taxid()
    }

    pub fn cross_references(&self) -> &Vec<CrossReference> {
        &self.cross_references
    }

    pub fn description(&self) -> &str {
        self.pre_summary.description()
    }
}
<|endoftext|>


<commit_before>#![deny(clippy)]

#[allow(dead_code)]
struct Foo;

impl Iterator for Foo {
    type Item = ();

    fn next(&mut self) -> Option<()> {
        let _ = self.len() == 0;
        unimplemented!()
    }
}

impl ExactSizeIterator for Foo {}

fn main() {}
<commit_msg>Allow unimplemented in other tests<commit_after>#![deny(clippy)]

#[allow(dead_code)]
struct Foo;

impl Iterator for Foo {
    type Item = ();

    #[allow(unimplemented)]
    fn next(&mut self) -> Option<()> {
        let _ = self.len() == 0;
        unimplemented!()
    }
}

impl ExactSizeIterator for Foo {}

fn main() {}
<|endoftext|>