<commit_before>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**

# Default values

- [method](struct.Solver.html#method.method): `Method::RK4`

- [weights](struct.Solver.html#method.weights) for the intermediate points:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

(Note that each internal value of the vector will be converted to `T` via
[T::from_str_radix()](../num_traits/trait.Num.html#tymethod.from_str_radix).)

# Example

```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /*
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            &Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<commit_msg>Small increment in documentation<commit_after>use traits::*;

pub enum Method {
    RK2,
    RK4,
}

/**

# Default values

When creating a new `Solver` with `Solver::new()`, this is the default
configuration:

- [method](struct.Solver.html#method.method): `Method::RK4`

- [weights](struct.Solver.html#method.weights) for the intermediate points:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

(Note that each internal value of the vector will be converted to `T` via
[T::from_str_radix()](../num_traits/trait.Num.html#tymethod.from_str_radix).)

# Example

```
use ode::{Method, Solver};

let ini_cond: Vec<f32> = vec![1., 2.];

// simple config
Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t])
    .method(Method::RK4)
    .run();

// complex config
let mut s = Solver::new(&ini_cond, |t: &f32, _: &Vec<f32>| vec![2.*t] );
s.method(Method::RK4);

// run the solver
let (times, pos) = s.run();
```
*/
pub struct Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    step: T,
    initial_conditions: Vec<T>,
    function: F,
}

impl<T, F> Solver<T, F>
    where T: Number,
          F: Fn(&T, &Vec<T>) -> Vec<T> {

    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /*
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            &Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(initial_conditions: &Vec<T>, function: F) -> Solver<T, F> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
            function:           function,
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T, F> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T, F> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn run(&self) -> (Vec<T>, Vec<Vec<T>>) {
        assert!(self.validate());

        (Vec::new(), Vec::new())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&vec![0., 0.],
                            |t: &f32, _: &Vec<f32>| -> Vec<f32> {
                                vec![2.*t]
                            });
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Format string literals.

use regex::Regex;
use unicode_segmentation::UnicodeSegmentation;

use config::Config;
use shape::Shape;
use utils::wrap_str;

const MIN_STRING: usize = 10;

pub struct StringFormat<'a> {
    pub opener: &'a str,
    pub closer: &'a str,
    pub line_start: &'a str,
    pub line_end: &'a str,
    pub shape: Shape,
    pub trim_end: bool,
    pub config: &'a Config,
}

impl<'a> StringFormat<'a> {
    pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> {
        StringFormat {
            opener: "\"",
            closer: "\"",
            line_start: " ",
            line_end: "\\",
            shape,
            trim_end: false,
            config,
        }
    }
}

// FIXME: simplify this!
pub fn rewrite_string<'a>(
    orig: &str,
    fmt: &StringFormat<'a>,
    max_width: Option<usize>,
) -> Option<String> {
    // Strip line breaks.
    let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap();
    let stripped_str = re.replace_all(orig, "$1");

    let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::<Vec<&str>>();
    let shape = fmt.shape;
    let indent = shape.indent.to_string_with_newline(fmt.config);
    let punctuation = ":,;.";

    // `cur_start` is the position in `orig` of the start of the current line.
    let mut cur_start = 0;
    let mut result = String::with_capacity(
        stripped_str
            .len()
            .checked_next_power_of_two()
            .unwrap_or(usize::max_value()),
    );
    result.push_str(fmt.opener);

    let ender_length = fmt.line_end.len();
    // If we cannot put at least a single character per line, the rewrite won't
    // succeed.
    let mut max_chars = shape
        .width
        .checked_sub(fmt.opener.len() + ender_length + 1)? + 1;

    // Snip a line at a time from `orig` until it is used up. Push the snippet
    // onto result.
    'outer: loop {
        // `cur_end` will be where we break the line, as an offset into `orig`.
        // Initialised to the maximum it could be (which may be beyond `orig`).
        let mut cur_end = cur_start + max_chars;

        // We can fit the rest of the string on this line, so we're done.
        if cur_end >= graphemes.len() {
            let line = &graphemes[cur_start..].join("");
            result.push_str(line);
            break 'outer;
        }

        // Push cur_end left until we reach whitespace (or the line is too small).
        while !graphemes[cur_end - 1].trim().is_empty() {
            cur_end -= 1;
            if cur_end < cur_start + MIN_STRING {
                // We couldn't find whitespace before the string got too small.
                // So start again at the max length and look for punctuation.
                cur_end = cur_start + max_chars;
                while !punctuation.contains(graphemes[cur_end - 1]) {
                    cur_end -= 1;

                    // If we can't break at whitespace or punctuation, grow the string instead.
                    if cur_end < cur_start + MIN_STRING {
                        cur_end = cur_start + max_chars;
                        while !(punctuation.contains(graphemes[cur_end - 1])
                            || graphemes[cur_end - 1].trim().is_empty())
                        {
                            cur_end += 1;
                            if cur_end == graphemes.len() {
                                let line = &graphemes[cur_start..].join("");
                                result.push_str(line);
                                break 'outer;
                            }
                        }
                        break;
                    }
                }
                break;
            }
        }
        // Make sure there is no whitespace to the right of the break.
        while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() {
            cur_end += 1;
        }

        // Make the current line and add it on to result.
        let raw_line = graphemes[cur_start..cur_end].join("");
        let line = if fmt.trim_end {
            raw_line.trim()
        } else {
            raw_line.as_str()
        };

        result.push_str(line);
        result.push_str(fmt.line_end);
        result.push_str(&indent);
        result.push_str(fmt.line_start);

        // The next line starts where the current line ends.
        cur_start = cur_end;

        if let Some(new_max_chars) = max_width {
            max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1;
        }
    }

    result.push_str(fmt.closer);
    wrap_str(result, fmt.config.max_width(), fmt.shape)
}

#[cfg(test)]
mod test {
    use super::{rewrite_string, StringFormat};
    use shape::{Indent, Shape};

    #[test]
    fn issue343() {
        let config = Default::default();
        let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config);
        rewrite_string("eq_", &fmt, None);
    }
}
<commit_msg>Seperate and optimize grapheme conditions<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Format string literals.

use regex::Regex;
use unicode_segmentation::UnicodeSegmentation;

use config::Config;
use shape::Shape;
use utils::wrap_str;

const MIN_STRING: usize = 10;

pub struct StringFormat<'a> {
    pub opener: &'a str,
    pub closer: &'a str,
    pub line_start: &'a str,
    pub line_end: &'a str,
    pub shape: Shape,
    pub trim_end: bool,
    pub config: &'a Config,
}

impl<'a> StringFormat<'a> {
    pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> {
        StringFormat {
            opener: "\"",
            closer: "\"",
            line_start: " ",
            line_end: "\\",
            shape,
            trim_end: false,
            config,
        }
    }
}

// FIXME: simplify this!
pub fn rewrite_string<'a>(
    orig: &str,
    fmt: &StringFormat<'a>,
    max_width: Option<usize>,
) -> Option<String> {
    // Strip line breaks.
    let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap();
    let stripped_str = re.replace_all(orig, "$1");

    let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::<Vec<&str>>();
    let shape = fmt.shape;
    let indent = shape.indent.to_string_with_newline(fmt.config);

    // `cur_start` is the position in `orig` of the start of the current line.
    let mut cur_start = 0;
    let mut result = String::with_capacity(
        stripped_str
            .len()
            .checked_next_power_of_two()
            .unwrap_or(usize::max_value()),
    );
    result.push_str(fmt.opener);

    let ender_length = fmt.line_end.len();
    // If we cannot put at least a single character per line, the rewrite won't
    // succeed.
    let mut max_chars = shape
        .width
        .checked_sub(fmt.opener.len() + ender_length + 1)? + 1;

    // Snip a line at a time from `orig` until it is used up. Push the snippet
    // onto result.
    'outer: loop {
        // `cur_end` will be where we break the line, as an offset into `orig`.
        // Initialised to the maximum it could be (which may be beyond `orig`).
        let mut cur_end = cur_start + max_chars;

        // We can fit the rest of the string on this line, so we're done.
        if cur_end >= graphemes.len() {
            let line = &graphemes[cur_start..].join("");
            result.push_str(line);
            break 'outer;
        }

        // Push cur_end left until we reach whitespace (or the line is too small).
        while !is_whitespace(graphemes[cur_end - 1]) {
            cur_end -= 1;
            if cur_end < cur_start + MIN_STRING {
                // We couldn't find whitespace before the string got too small.
                // So start again at the max length and look for punctuation.
                cur_end = cur_start + max_chars;
                while !is_punctuation(graphemes[cur_end - 1]) {
                    cur_end -= 1;

                    // If we can't break at whitespace or punctuation, grow the string instead.
                    if cur_end < cur_start + MIN_STRING {
                        cur_end = cur_start + max_chars;
                        while !(is_punctuation(graphemes[cur_end - 1])
                            || is_whitespace(graphemes[cur_end - 1]))
                        {
                            cur_end += 1;
                            if cur_end == graphemes.len() {
                                let line = &graphemes[cur_start..].join("");
                                result.push_str(line);
                                break 'outer;
                            }
                        }
                        break;
                    }
                }
                break;
            }
        }
        // Make sure there is no whitespace to the right of the break.
        while cur_end < stripped_str.len() && is_whitespace(graphemes[cur_end]) {
            cur_end += 1;
        }

        // Make the current line and add it on to result.
        let raw_line = graphemes[cur_start..cur_end].join("");
        let line = if fmt.trim_end {
            raw_line.trim()
        } else {
            raw_line.as_str()
        };

        result.push_str(line);
        result.push_str(fmt.line_end);
        result.push_str(&indent);
        result.push_str(fmt.line_start);

        // The next line starts where the current line ends.
        cur_start = cur_end;

        if let Some(new_max_chars) = max_width {
            max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1;
        }
    }

    result.push_str(fmt.closer);
    wrap_str(result, fmt.config.max_width(), fmt.shape)
}

fn is_whitespace(grapheme: &str) -> bool {
    grapheme.chars().all(|c| c.is_whitespace())
}

fn is_punctuation(grapheme: &str) -> bool {
    match grapheme.as_bytes()[0] {
        b':' | b',' | b';' | b'.' => true,
        _ => false,
    }
}

#[cfg(test)]
mod test {
    use super::{rewrite_string, StringFormat};
    use shape::{Indent, Shape};

    #[test]
    fn issue343() {
        let config = Default::default();
        let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config);
        rewrite_string("eq_", &fmt, None);
    }
}
<|endoftext|>


<commit_before>struct Stack {
    content: Vec<u32>,
}

impl Stack {
    fn push(&mut self, d: u32) -> Result<u32, &str> {
        self.content.push(d);
        Ok(d);
    }

    fn pop(&mut self) -> u32 {
        self.content.pop().expect("Stack empty!")
    }

    fn addDigit(&mut self, c: char) -> Result<u32, &str> {
        let d = c.to_digit(10);

        match d {
            Some(n) => self.push(n),
            None    => Err("Invalid character"),
        }
    }

    fn multiply(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l * r);
    }

    fn add(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l + r);
    }

    fn subtract(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l - r);
    }

    fn divide(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l / r);
    }
}

fn evaluate(program: Vec<char>) {
    let mut stack = Stack { content: vec![] };

    for c in program {
        let answer: Result<u32, &str> = match c {
            '*' => stack.multiply(),
            '+' => stack.add(),
            '-' => stack.subtract(),
            '/' => stack.divide(),
            _   => stack.addDigit(c),
        };

        match answer {
            Ok(n) => continue,
            Err(e) => {
                println!("{}", e);
                break;
            }
        };
    }

    for c in stack.content {
        println!("{}", c);
    }
}

fn main() {
    let program: Vec<char> = "3 4 * 2 * 1 /".chars().filter(|&c| c != ' ').collect();

    evaluate(program);
}
<commit_msg>Only one more compile error left<commit_after>struct Stack {
    content: Vec<u32>,
}

impl Stack {
    fn push(&mut self, d: u32) -> Result<u32, _> {
        self.content.push(d);
        Ok(d);
    }

    fn pop(&mut self) -> u32 {
        self.content.pop().expect("Stack empty!")
    }

    fn addDigit(&mut self, c: char) -> Result<u32, &str> {
        let d = c.to_digit(10);

        match d {
            Some(n) => self.push(n),
            None    => Err("Invalid character"),
        }
    }

    fn multiply(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l * r);
    }

    fn add(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l + r);
    }

    fn subtract(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l - r);
    }

    fn divide(&mut self) -> Result<u32, &str> {
        let r = self.pop();
        let l = self.pop();

        self.push(l / r);
    }
}

fn evaluate(program: Vec<char>) {
    let mut stack = Stack { content: vec![] };

    for c in program {
        let answer: Result<u32, &str> = match c {
            '*' => stack.multiply(),
            '+' => stack.add(),
            '-' => stack.subtract(),
            '/' => stack.divide(),
            _   => stack.addDigit(c),
        };

        match answer {
            Ok(n) => continue,
            Err(e) => {
                println!("{}", e);
                break;
            }
        };
    }

    for c in stack.content {
        println!("{}", c);
    }
}

fn main() {
    let program: Vec<char> = "3 4 * 2 * 1 /".chars().filter(|&c| c != ' ').collect();

    evaluate(program);
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use rand::{thread_rng, sample};

struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn reveal<'a>(&self) -> Result<i32, &'a str> {
        match (self.content.len(), self.digits.len()) {
            (1, 0) => Ok(self.content[0]),
            (1, _) => Err("Did not use all digits!"),
            _ => Err("Invalid formula!"),
        }
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let (r, l) = (self.pop(), self.pop());

        match (l, r) {
            (Some(x), Some(y)) => self.push(f(x, y)),
            _ => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            //return answer;
            //return Err("Program error");
            println!("Actual: {}", answer.unwrap_err());
            break;
        }
    }

    stack.reveal()
}

fn main() {
    let goal: i32 = 24;
    let mut rng = thread_rng();

    println!("GUESSING GAME!

RULES

  * Using only the given digits, create an expression that evaluates to 24.
  * All digits must be used.
  * Each digit may only be used once.
  * Expressions must be in Reverse-Polish Notation (RPN).
  * Only +, -, * and / are allowed.
  * Order of the digits is not important.\n");

    loop {
        let mut program = String::new();
        let digits = sample(&mut rng, 1..9, 4);

        println!("Your digits are: {}, {}, {} and {}\n", digits[0], digits[1], digits[2], digits[3]);
        println!("Enter an expression:\n");

        io::stdin().read_line(&mut program)
            .ok()
            .expect("Could not read input.");

        let parsed = program
            .trim()
            .chars()
            .filter(|&c| c != ' ')
            .collect();

        match evaluate(parsed, digits) {
            Ok(n) => if n == goal {
                println!("\nWell done!\n");
                break;
            } else {
                println!("\nNice try, but {} is not {}!\n", n, goal);
            },
            Err(s) => {
                println!("\nOops: {}\n", s);
            },
        }
    }
}
<commit_msg>Cleaned up digit printing in 24_game<commit_after>extern crate rand;

use std::io;
use rand::{thread_rng, sample};

struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn reveal<'a>(&self) -> Result<i32, &'a str> {
        match (self.content.len(), self.digits.len()) {
            (1, 0) => Ok(self.content[0]),
            (1, _) => Err("Did not use all digits!"),
            _ => Err("Invalid formula!"),
        }
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let (r, l) = (self.pop(), self.pop());

        match (l, r) {
            (Some(x), Some(y)) => self.push(f(x, y)),
            _ => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            //return answer;
            //return Err("Program error");
            println!("Actual: {}", answer.unwrap_err());
            break;
        }
    }

    stack.reveal()
}

fn main() {
    let goal: i32 = 24;
    let mut rng = thread_rng();

    println!("GUESSING GAME!

RULES

  * Using only the given digits, create an expression that evaluates to 24.
  * All digits must be used.
  * Each digit may only be used once.
  * Expressions must be in Reverse-Polish Notation (RPN).
  * Only +, -, * and / are allowed.
  * Order of the digits is not important.\n");

    loop {
        let mut program = String::new();
        let digits = sample(&mut rng, 1..9, 4);

        println!("Your digits are: {:?}\n", digits);
        println!("Enter an expression:\n");

        io::stdin().read_line(&mut program)
            .ok()
            .expect("Could not read input.");

        let parsed = program
            .trim()
            .chars()
            .filter(|&c| c != ' ')
            .collect();

        match evaluate(parsed, digits) {
            Ok(n) => if n == goal {
                println!("\nWell done!\n");
                break;
            } else {
                println!("\nNice try, but {} is not {}!\n", n, goal);
            },
            Err(s) => {
                println!("\nOops: {}\n", s);
            },
        }
    }
}
<|endoftext|>


<commit_before>use redox::Vec;

pub struct AvlNode<T> {
    value: T,
    left: Option<AvlNodeId>, // ID for left node
    right: Option<AvlNodeId>, // ID for right node
}

#[derive(Copy, Clone)]
pub struct AvlNodeId {
    index: usize,
    time_stamp: u64,
}

impl AvlNodeId {
    pub fn get<'a, T>(&self, avl: &'a Avl<T>) -> &'a AvlNode<T> {
        let ref slot = avl.nodes[self.index];
        if slot.time_stamp == self.time_stamp {
            slot.node.as_ref().unwrap()
        } else {
            panic!("AvlNodeId had invalid time_stamp");
        }
    }

    pub fn try_get<'a, T>(&self, avl: &'a Avl<T>) -> Option<&'a AvlNode<T>> {
        avl.nodes
           .get(self.index)
           .and_then(|slot| {
               if slot.time_stamp == self.time_stamp {
                   slot.node.as_ref()
               } else {
                   None
               }
           })
    }

    pub fn get_mut<'a, T>(&self, avl: &'a mut Avl<T>) -> &'a mut AvlNode<T> {
        let ref mut slot = avl.nodes[self.index];
        if slot.time_stamp == self.time_stamp {
            slot.node.as_mut().unwrap()
        } else {
            panic!("AvlNodeId had invalid time_stamp");
        }
    }

    pub fn try_get_mut<'a, T>(&self, avl: &'a mut Avl<T>) -> Option<&'a mut AvlNode<T>> {
        avl.nodes
           .get_mut(self.index)
           .and_then(|slot| {
               if slot.time_stamp == self.time_stamp {
                   slot.node.as_mut()
               } else {
                   None
               }
           })
    }
}

pub struct Avl<T> {
    root: usize, // Index of the root node
    nodes: Vec<AvlSlot<T>>,
    free_list: Vec<usize>,
}

impl<T> Avl<T> {
    pub fn new() -> Self {
        Avl {
            root: 0,
            nodes: Vec::new(),
            free_list: Vec::new(),
        }
    }

    pub fn insert(&mut self, value: T) -> AvlNodeId {
        // TODO this is just a placeholder, we need to deal with all the fancy rotation stuff that
        // AVL trees do
        self.allocate_node(value)
    }

    // Performs a left rotation on a tree/subtree.
    // Returns the replace the specified node with
    fn rotate_left(&mut self, node: AvlNodeId) -> AvlNodeId {
        // Keep track of the original node positions
        // For a rotate left, the right child node must exist
        let r = node.get(self).right.unwrap();
        let rl = r.get(self).left;

        let ret = r;
        node.get_mut(self).right = rl;
        ret.get_mut(self).left = Some(node);

        ret
    }

    // Performs a right rotation on a tree/subtree.
    // Returns the replace the specified node with
    fn rotate_right(&mut self, node: AvlNodeId) -> AvlNodeId {
        // Keep track of the original node positions
        // For a rotate right, the left child node must exist
        let l = node.get(self).left.unwrap();
        let lr = l.get(self).right;

        let ret = l;
        node.get_mut(self).left = lr;
        ret.get_mut(self).right = Some(node);

        ret
    }

    // performs a left-right double rotation on a tree/subtree.
    fn rotate_leftright(&mut self, node: AvlNodeId) -> AvlNodeId {
        let l = node.get(self).left.unwrap();
        let new_l = self.rotate_left(l); // Left node needs to exist
        node.get_mut(self).left = Some(new_l);
        self.rotate_right(node)
    }

    // performs a right-left double rotation on a tree/subtree.
    fn rotate_rightleft(&mut self, node: AvlNodeId) -> AvlNodeId {
        let r = node.get(self).right.unwrap();
        let new_r = self.rotate_right(r); // Right node needs to exist
        node.get_mut(self).right = Some(new_r);
        self.rotate_left(node)
    }

    // _ins is the implementation of the binary tree insert function. Lesser values will be stored on
    // the left, while greater values will be stored on the right. No duplicates are allowed.
    /*fn _ins(&mut self, node_index: Option<AvlNodeId>, value: T) -> AvlNodeId {
        let node =
            match node_index {
                Some(node) => {
                    // Node exists, check which way to branch.
                    if n == node->val {
                        return node;
                    else if (n < node->val)
                        _ins(n, node->left);
                    else if (n > node->val)
                        _ins(n, node->right);
                },
                None => {
                    // The node doesn't exist, create it here.
                    self.allocate_node(value)
                },
            };

        rebalance(node);
    }*/

    // _rebalance rebalances the provided node
    /*fn rebalance(node: AvlNodeId) {
        if !node {
            return;
        }

        let balance = self.height(node.get(self).left) - self.height(node.right);
        if balance == 2 { // left
            let lbalance = self.height(node.left.left) - self.height(node.left.right);
            if lbalance == 0 || lbalance == 1 { // left left - need to rotate right
                rotate_right(node);
            } else if lbalance == -1 { // left right
                rotate_leftright(node); // function name is just a coincidence
            }
        }
        else if balance == -2 { // right
            let rbalance = _height(node->right->left) - _height(node->right->right);
            if rbalance == 1 { // right left
                rotate_rightleft(node); // function name is just a coincidence
            } else if (rbalance == 0 || rbalance == -1) { // right right - need to rotate left
                rotate_left(node);
            }
        }
    }*/

    // height gets the height of a tree or subtree
    fn height(&self, node: Option<AvlNodeId>) -> i64 {
        match node {
            Some(node) => {
                let left_height = self.height(node.get(self).left);
                let right_height = self.height(node.get(self).right);

                if left_height > right_height {
                    left_height+1
                } else {
                    right_height+1
                }
            },
            None => { -1 },
        }
    }

    fn allocate_node(&mut self, value: T) -> AvlNodeId {
        match self.free_list.pop() {
            Some(index) => {
                AvlNodeId { time_stamp: self.nodes[index].time_stamp+1, index: index }
            },
            None => {
                // No free slots, create a new one
                let id = AvlNodeId { index: self.nodes.len(), time_stamp: 0 };
                self.nodes.push(AvlSlot { time_stamp: 0,
                                          node: Some(AvlNode { value: value, left: None, right: None }) });
                id
            },
        }
    }

    fn free_node(&mut self, id: AvlNodeId) -> AvlNode<T> {
        self.free_list.push(id.index);

        // NOTE: We unwrap here, because we trust that `id` points to a valid node, because
        // only we can create and free AvlNodes and their AvlNodeIds
        self.nodes[id.index].node.take().unwrap()
    }
}

struct AvlSlot<T> {
    time_stamp: u64,
    node: Option<AvlNode<T>>,
}
<commit_msg>AvlTree::rebalance compiles<commit_after>use redox::Vec;

pub struct AvlNode<T> {
    value: T,
    left: Option<AvlNodeId>, // ID for left node
    right: Option<AvlNodeId>, // ID for right node
}

#[derive(Copy, Clone)]
pub struct AvlNodeId {
    index: usize,
    time_stamp: u64,
}

impl AvlNodeId {
    pub fn get<'a, T>(&self, avl: &'a Avl<T>) -> &'a AvlNode<T> {
        let ref slot = avl.nodes[self.index];
        if slot.time_stamp == self.time_stamp {
            slot.node.as_ref().unwrap()
        } else {
            panic!("AvlNodeId had invalid time_stamp");
        }
    }

    pub fn try_get<'a, T>(&self, avl: &'a Avl<T>) -> Option<&'a AvlNode<T>> {
        avl.nodes
           .get(self.index)
           .and_then(|slot| {
               if slot.time_stamp == self.time_stamp {
                   slot.node.as_ref()
               } else {
                   None
               }
           })
    }

    pub fn get_mut<'a, T>(&self, avl: &'a mut Avl<T>) -> &'a mut AvlNode<T> {
        let ref mut slot = avl.nodes[self.index];
        if slot.time_stamp == self.time_stamp {
            slot.node.as_mut().unwrap()
        } else {
            panic!("AvlNodeId had invalid time_stamp");
        }
    }

    pub fn try_get_mut<'a, T>(&self, avl: &'a mut Avl<T>) -> Option<&'a mut AvlNode<T>> {
        avl.nodes
           .get_mut(self.index)
           .and_then(|slot| {
               if slot.time_stamp == self.time_stamp {
                   slot.node.as_mut()
               } else {
                   None
               }
           })
    }
}

pub struct Avl<T> {
    root: usize, // Index of the root node
    nodes: Vec<AvlSlot<T>>,
    free_list: Vec<usize>,
}

impl<T> Avl<T> {
    pub fn new() -> Self {
        Avl {
            root: 0,
            nodes: Vec::new(),
            free_list: Vec::new(),
        }
    }

    pub fn insert(&mut self, value: T) -> AvlNodeId {
        // TODO this is just a placeholder, we need to deal with all the fancy rotation stuff that
        // AVL trees do
        self.allocate_node(value)
    }

    // Performs a left rotation on a tree/subtree.
    // Returns the replace the specified node with
    fn rotate_left(&mut self, node: AvlNodeId) -> AvlNodeId {
        // Keep track of the original node positions
        // For a rotate left, the right child node must exist
        let r = node.get(self).right.unwrap();
        let rl = r.get(self).left;

        let ret = r;
        node.get_mut(self).right = rl;
        ret.get_mut(self).left = Some(node);

        ret
    }

    // Performs a right rotation on a tree/subtree.
    // Returns the replace the specified node with
    fn rotate_right(&mut self, node: AvlNodeId) -> AvlNodeId {
        // Keep track of the original node positions
        // For a rotate right, the left child node must exist
        let l = node.get(self).left.unwrap();
        let lr = l.get(self).right;

        let ret = l;
        node.get_mut(self).left = lr;
        ret.get_mut(self).right = Some(node);

        ret
    }

    // performs a left-right double rotation on a tree/subtree.
    fn rotate_leftright(&mut self, node: AvlNodeId) -> AvlNodeId {
        let l = node.get(self).left.unwrap();
        let new_l = self.rotate_left(l); // Left node needs to exist
        node.get_mut(self).left = Some(new_l);
        self.rotate_right(node)
    }

    // performs a right-left double rotation on a tree/subtree.
    fn rotate_rightleft(&mut self, node: AvlNodeId) -> AvlNodeId {
        let r = node.get(self).right.unwrap();
        let new_r = self.rotate_right(r); // Right node needs to exist
        node.get_mut(self).right = Some(new_r);
        self.rotate_left(node)
    }

    // _ins is the implementation of the binary tree insert function. Lesser values will be stored on
    // the left, while greater values will be stored on the right. No duplicates are allowed.
    /*fn _ins(&mut self, node_index: Option<AvlNodeId>, value: T) -> AvlNodeId {
        let node =
            match node_index {
                Some(node) => {
                    // Node exists, check which way to branch.
                    if n == node->val {
                        return node;
                    else if (n < node->val)
                        _ins(n, node->left);
                    else if (n > node->val)
                        _ins(n, node->right);
                },
                None => {
                    // The node doesn't exist, create it here.
                    self.allocate_node(value)
                },
            };

        rebalance(node)
    }*/

    // _rebalance rebalances the provided node
    fn rebalance(&mut self, node: AvlNodeId) -> AvlNodeId {
        let balance = self.height(node.get(self).left) - self.height(node.get(self).right);
        if balance == 2 { // left
            let lbalance = self.height(node.get(self).left.unwrap().get(self).left) -
                           self.height(node.get(self).left.unwrap().get(self).right);
            if lbalance == 0 || lbalance == 1 { // left left - need to rotate right
                return self.rotate_right(node);
            } else if lbalance == -1 { // left right
                return self.rotate_leftright(node); // function name is just a coincidence
            }
        } else if balance == -2 { // right
            let rbalance = self.height(node.get(self).right.unwrap().get(self).left) -
                           self.height(node.get(self).right.unwrap().get(self).right);
            if rbalance == 1 { // right left
                return self.rotate_rightleft(node); // function name is just a coincidence
            } else if rbalance == 0 || rbalance == -1 { // right right - need to rotate left
                return self.rotate_left(node);
            }
        }

        node
    }

    // height gets the height of a tree or subtree
    fn height(&self, node: Option<AvlNodeId>) -> i64 {
        match node {
            Some(node) => {
                let left_height = self.height(node.get(self).left);
                let right_height = self.height(node.get(self).right);

                if left_height > right_height {
                    left_height+1
                } else {
                    right_height+1
                }
            },
            None => { -1 },
        }
    }

    fn allocate_node(&mut self, value: T) -> AvlNodeId {
        match self.free_list.pop() {
            Some(index) => {
                AvlNodeId { time_stamp: self.nodes[index].time_stamp+1, index: index }
            },
            None => {
                // No free slots, create a new one
                let id = AvlNodeId { index: self.nodes.len(), time_stamp: 0 };
                self.nodes.push(AvlSlot { time_stamp: 0,
                                          node: Some(AvlNode { value: value, left: None, right: None }) });
                id
            },
        }
    }

    fn free_node(&mut self, id: AvlNodeId) -> AvlNode<T> {
        self.free_list.push(id.index);

        // NOTE: We unwrap here, because we trust that `id` points to a valid node, because
        // only we can create and free AvlNodes and their AvlNodeIds
        self.nodes[id.index].node.take().unwrap()
    }
}

struct AvlSlot<T> {
    time_stamp: u64,
    node: Option<AvlNode<T>>,
}
<|endoftext|>


<commit_before>mod stack;
mod pc;
mod memory;
mod params;
mod account;
mod cost;
mod run;

pub use self::memory::{Memory, SeqMemory};
pub use self::stack::Stack;
pub use self::pc::PC;
pub use self::params::{BlockHeader, Transaction};
pub use self::account::{Account, Storage, HashMapStorage, Log};

use self::cost::{gas_cost, gas_refund, CostAggregrator};
use self::run::run_opcode;
use std::collections::hash_map;
use utils::gas::Gas;
use utils::address::Address;
use utils::bigint::{M256, U256};

#[derive(Debug)]
pub enum ExecutionError {
    EmptyGas,
    StackUnderflow,
    StackOverflow,
    InvalidOpcode,
    PCOverflow,
    PCBadJumpDest,
    PCTooLarge, // The current implementation only support code size with usize::maximum.
    MemoryTooLarge,
    DataTooLarge,
    CodeTooLarge,
    RequireAccount(Address),
    RequireAccountCode(Address),
    RequireBlockhash(M256),
    Stopped
}

#[derive(Clone)]
pub enum Commitment<S> {
    Full {
        address: Address,
        balance: U256,
        storage: S,
        code: Vec<u8>,
    },
    Code {
        address: Address,
        code: Vec<u8>,
    },
    Blockhash {
        number: M256,
        hash: M256,
    },
}

#[derive(Debug)]
pub enum CommitError {
    AlreadyCommitted,
    StateChanged
}

pub type ExecutionResult<T> = ::std::result::Result<T, ExecutionError>;

pub type SeqMachine = Machine<SeqMemory, HashMapStorage>;

pub struct Machine<M, S> {
    pc: PC,
    memory: M,
    stack: Stack,
    transaction: Transaction,
    block: BlockHeader,
    cost_aggregrator: CostAggregrator,
    return_values: Vec<u8>,
    accounts: hash_map::HashMap<Address, Account<S>>,
    blockhashes: hash_map::HashMap<M256, M256>,
    valid_pc: bool,
    used_gas: Gas,
    refunded_gas: Gas,

    homestead: bool,
    eip150: bool,
    eip160: bool,
}

impl<M: Memory + Default, S: Storage> Machine<M, S> {
    pub fn new(transaction: Transaction, block: BlockHeader) -> Self {
        Self {
            pc: PC::default(),
            memory: M::default(),
            stack: Stack::default(),
            transaction: transaction,
            block: block,
            cost_aggregrator: CostAggregrator::default(),
            return_values: Vec::new(),
            accounts: hash_map::HashMap::new(),
            blockhashes: hash_map::HashMap::new(),
            valid_pc: false,
            used_gas: Gas::zero(),
            refunded_gas: Gas::zero(),

            homestead: false,
            eip150: false,
            eip160: false,
        }
    }
}

impl<M: Memory + Default, S: Storage + Default> Machine<M, S> {
    pub fn pc(&self) -> Option<&PC> {
        if self.valid_pc {
            Some(&self.pc)
        } else {
            None
        }
    }

    pub fn memory(&self) -> &M {
        &self.memory
    }

    pub fn stack(&self) -> &Stack {
        &self.stack
    }

    pub fn transaction(&self) -> &Transaction {
        &self.transaction
    }

    pub fn block(&self) -> &BlockHeader {
        &self.block
    }

    pub fn accounts(&self) -> hash_map::Values<Address, Account<S>> {
        self.accounts.values()
    }

    pub fn return_values(&self) -> &[u8] {
        self.return_values.as_slice()
    }

    pub fn active_memory_len(&self) -> M256 {
        self.cost_aggregrator.active_memory_len()
    }

    pub fn owner(&self) -> Address {
        match self.transaction {
            Transaction::MessageCall {
                to: to,
                ..
            } => to,
            Transaction::ContractCreation {
                ..
            } => unimplemented!(),
        }
    }

    pub fn available_gas(&self) -> Gas {
        self.transaction.gas_limit() - self.used_gas
    }

    pub fn homestead(&self) -> bool {
        self.homestead
    }

    pub fn set_homestead(&mut self, val: bool) {
        self.homestead = val;
    }

    pub fn eip150(&self) -> bool {
        self.eip150
    }

    pub fn set_eip150(&mut self, val: bool) {
        self.eip150 = val;
    }

    pub fn eip160(&self) -> bool {
        self.eip160
    }

    pub fn set_eip160(&mut self, val: bool) {
        self.eip160 = val;
    }

    pub fn commit(&mut self, commitment: Commitment<S>) -> Result<(), CommitError> {
        match commitment {
            Commitment::Full {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
            } => {
                if self.accounts.contains_key(&address) {
                    return Err(CommitError::AlreadyCommitted);
                }

                if address == self.owner() {
                    self.pc = PC::new(code.as_slice());
                    self.valid_pc = true;
                }

                self.accounts.insert(address, Account::Full {
                    address: address,
                    balance: balance,
                    storage: storage,
                    code: code,
                    appending_logs: Vec::new(),
                });
            },
            Commitment::Code {
                address: address,
                code: code,
            } => {
                if self.accounts.contains_key(&address) {
                    return Err(CommitError::AlreadyCommitted);
                }

                self.accounts.insert(address, Account::Code {
                    address: address,
                    code: code
                });
            },
            Commitment::Blockhash {
                number: number,
                hash: hash,
            } => {
                if self.blockhashes.contains_key(&number) {
                    return Err(CommitError::AlreadyCommitted);
                }

                self.blockhashes.insert(number, hash);
            },
        }
        Ok(())
    }

    fn account_log(&mut self, address: Address, data: &[u8], topics: &[M256]) -> ExecutionResult<()> {
        match self.accounts.get_mut(&address) {
            Some(&mut Account::Full {
                appending_logs: ref mut appending_logs,
                ..
            }) => {
                appending_logs.push(Log {
                    data: data.into(),
                    topics: topics.into(),
                });
                Ok(())
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_code(&self, address: Address) -> ExecutionResult<&[u8]> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                code: ref code,
                ..
            }) => {
                Ok(code.as_slice())
            },
            Some(&Account::Code {
                code: ref code,
                ..
            }) => {
                Ok(code.as_slice())
            },
            _ => {
                Err(ExecutionError::RequireAccountCode(address))
            }
        }
    }

    fn account_balance(&self, address: Address) -> ExecutionResult<U256> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                balance: balance,
                ..
            }) => {
                Ok(balance)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_balance_topup(&mut self, address: Address, topup: U256) -> ExecutionResult<()> {
        let account = match self.accounts.remove(&address) {
            Some(Account::Full {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
                appending_logs: appending_logs,
            }) => {
                Account::Full {
                    address: address,
                    balance: balance + topup,
                    storage: storage,
                    code: code,
                    appending_logs: appending_logs,
                }
            },
            Some(Account::Code {
                ..
            }) => {
                return Err(ExecutionError::RequireAccount(address));
            }
            Some(Account::Remove(address)) => {
                Account::Full {
                    address: address,
                    balance: topup,
                    storage: S::default(),
                    code: Vec::new(),
                    appending_logs: Vec::new(),
                }
            },
            Some(Account::Topup(address, old_topup)) => {
                Account::Topup(address, old_topup + topup)
            },
            None => {
                Account::Topup(address, topup)
            },
        };
        self.accounts.insert(address, account);
        Ok(())
    }

    fn account_remove(&mut self, address: Address) {
        self.accounts.insert(address, Account::Remove(address));
    }

    fn account_storage(&self, address: Address) -> ExecutionResult<&S> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                storage: ref storage,
                ..
            }) => {
                Ok(storage)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_storage_mut(&mut self, address: Address) -> ExecutionResult<&mut S> {
        match self.accounts.get_mut(&address) {
            Some(&mut Account::Full {
                storage: ref mut storage,
                ..
            }) => {
                Ok(storage)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn blockhash(&mut self, number: M256) -> ExecutionResult<M256> {
        match self.blockhashes.get(&number) {
            Some(val) => Ok(*val),
            None => Err(ExecutionError::RequireBlockhash(number)),
        }
    }

    pub fn peek_cost(&self) -> ExecutionResult<Gas> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        let opcode = self.pc.peek_opcode()?;
        let aggregrator = self.cost_aggregrator;
        let (gas, agg) = gas_cost(opcode, &self, aggregrator)?;
        Ok(gas)
    }

    pub fn step(&mut self) -> ExecutionResult<()> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        begin_rescuable!(self, &mut Self, __);
        if self.pc.stopped() {
            trr!(Err(ExecutionError::Stopped), __);
        }

        let position = self.pc.position();
        on_rescue!(|machine| {
            machine.pc.jump_unchecked(position);
        }, __);

        let opcode = trr!(self.pc.read_opcode(), __);
        let available_gas = self.available_gas();
        let cost_aggregrator = self.cost_aggregrator;
        let (gas, agg) = trr!(gas_cost(opcode, self, cost_aggregrator), __);
        let refunded = trr!(gas_refund(opcode, self), __);

        if gas > self.available_gas() {
            trr!(Err(ExecutionError::EmptyGas), __);
        }

        trr!(run_opcode(opcode, self, available_gas - gas), __);

        self.cost_aggregrator = agg;
        self.used_gas = self.used_gas + gas;
        self.refunded_gas = self.refunded_gas + refunded;

        end_rescuable!(__);
        Ok(())
    }

    pub fn fire(&mut self) -> ExecutionResult<()> {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {
                    ExecutionError::Stopped => return Ok(()),
                    err => return Err(err),
                }
            }
        }
    }
}
<commit_msg>Problem: no call depth representation in Machine Solution: add depth field<commit_after>mod stack;
mod pc;
mod memory;
mod params;
mod account;
mod cost;
mod run;

pub use self::memory::{Memory, SeqMemory};
pub use self::stack::Stack;
pub use self::pc::PC;
pub use self::params::{BlockHeader, Transaction};
pub use self::account::{Account, Storage, HashMapStorage, Log};

use self::cost::{gas_cost, gas_refund, CostAggregrator};
use self::run::run_opcode;
use std::collections::hash_map;
use utils::gas::Gas;
use utils::address::Address;
use utils::bigint::{M256, U256};

#[derive(Debug)]
pub enum ExecutionError {
    EmptyGas,
    StackUnderflow,
    StackOverflow,
    InvalidOpcode,
    PCOverflow,
    PCBadJumpDest,
    PCTooLarge, // The current implementation only support code size with usize::maximum.
    MemoryTooLarge,
    DataTooLarge,
    CodeTooLarge,
    RequireAccount(Address),
    RequireAccountCode(Address),
    RequireBlockhash(M256),
    Stopped
}

#[derive(Clone)]
pub enum Commitment<S> {
    Full {
        address: Address,
        balance: U256,
        storage: S,
        code: Vec<u8>,
    },
    Code {
        address: Address,
        code: Vec<u8>,
    },
    Blockhash {
        number: M256,
        hash: M256,
    },
}

#[derive(Debug)]
pub enum CommitError {
    AlreadyCommitted,
    StateChanged
}

pub type ExecutionResult<T> = ::std::result::Result<T, ExecutionError>;

pub type SeqMachine = Machine<SeqMemory, HashMapStorage>;

pub struct Machine<M, S> {
    pc: PC,
    memory: M,
    stack: Stack,
    transaction: Transaction,
    block: BlockHeader,
    cost_aggregrator: CostAggregrator,
    return_values: Vec<u8>,
    accounts: hash_map::HashMap<Address, Account<S>>,
    blockhashes: hash_map::HashMap<M256, M256>,
    valid_pc: bool,
    used_gas: Gas,
    refunded_gas: Gas,
    depth: usize,

    homestead: bool,
    eip150: bool,
    eip160: bool,
}

impl<M: Memory + Default, S: Storage> Machine<M, S> {
    pub fn new(transaction: Transaction, block: BlockHeader) -> Self {
        Machine::with_depth(transaction, block, 1)
    }

    pub fn with_depth(transaction: Transaction, block: BlockHeader, depth: usize) -> Self {
        Self {
            pc: PC::default(),
            memory: M::default(),
            stack: Stack::default(),
            transaction: transaction,
            block: block,
            cost_aggregrator: CostAggregrator::default(),
            return_values: Vec::new(),
            accounts: hash_map::HashMap::new(),
            blockhashes: hash_map::HashMap::new(),
            valid_pc: false,
            used_gas: Gas::zero(),
            refunded_gas: Gas::zero(),
            depth: depth,

            homestead: false,
            eip150: false,
            eip160: false,
        }
    }
}

impl<M: Memory + Default, S: Storage + Default> Machine<M, S> {
    pub fn pc(&self) -> Option<&PC> {
        if self.valid_pc {
            Some(&self.pc)
        } else {
            None
        }
    }

    pub fn memory(&self) -> &M {
        &self.memory
    }

    pub fn stack(&self) -> &Stack {
        &self.stack
    }

    pub fn transaction(&self) -> &Transaction {
        &self.transaction
    }

    pub fn block(&self) -> &BlockHeader {
        &self.block
    }

    pub fn accounts(&self) -> hash_map::Values<Address, Account<S>> {
        self.accounts.values()
    }

    pub fn return_values(&self) -> &[u8] {
        self.return_values.as_slice()
    }

    pub fn active_memory_len(&self) -> M256 {
        self.cost_aggregrator.active_memory_len()
    }

    pub fn owner(&self) -> Address {
        match self.transaction {
            Transaction::MessageCall {
                to: to,
                ..
            } => to,
            Transaction::ContractCreation {
                ..
            } => unimplemented!(),
        }
    }

    pub fn available_gas(&self) -> Gas {
        self.transaction.gas_limit() - self.used_gas
    }

    pub fn homestead(&self) -> bool {
        self.homestead
    }

    pub fn set_homestead(&mut self, val: bool) {
        self.homestead = val;
    }

    pub fn eip150(&self) -> bool {
        self.eip150
    }

    pub fn set_eip150(&mut self, val: bool) {
        self.eip150 = val;
    }

    pub fn eip160(&self) -> bool {
        self.eip160
    }

    pub fn set_eip160(&mut self, val: bool) {
        self.eip160 = val;
    }

    pub fn commit(&mut self, commitment: Commitment<S>) -> Result<(), CommitError> {
        match commitment {
            Commitment::Full {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
            } => {
                if self.accounts.contains_key(&address) {
                    return Err(CommitError::AlreadyCommitted);
                }

                if address == self.owner() {
                    self.pc = PC::new(code.as_slice());
                    self.valid_pc = true;
                }

                self.accounts.insert(address, Account::Full {
                    address: address,
                    balance: balance,
                    storage: storage,
                    code: code,
                    appending_logs: Vec::new(),
                });
            },
            Commitment::Code {
                address: address,
                code: code,
            } => {
                if self.accounts.contains_key(&address) {
                    return Err(CommitError::AlreadyCommitted);
                }

                self.accounts.insert(address, Account::Code {
                    address: address,
                    code: code
                });
            },
            Commitment::Blockhash {
                number: number,
                hash: hash,
            } => {
                if self.blockhashes.contains_key(&number) {
                    return Err(CommitError::AlreadyCommitted);
                }

                self.blockhashes.insert(number, hash);
            },
        }
        Ok(())
    }

    fn account_log(&mut self, address: Address, data: &[u8], topics: &[M256]) -> ExecutionResult<()> {
        match self.accounts.get_mut(&address) {
            Some(&mut Account::Full {
                appending_logs: ref mut appending_logs,
                ..
            }) => {
                appending_logs.push(Log {
                    data: data.into(),
                    topics: topics.into(),
                });
                Ok(())
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_code(&self, address: Address) -> ExecutionResult<&[u8]> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                code: ref code,
                ..
            }) => {
                Ok(code.as_slice())
            },
            Some(&Account::Code {
                code: ref code,
                ..
            }) => {
                Ok(code.as_slice())
            },
            _ => {
                Err(ExecutionError::RequireAccountCode(address))
            }
        }
    }

    fn account_balance(&self, address: Address) -> ExecutionResult<U256> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                balance: balance,
                ..
            }) => {
                Ok(balance)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_balance_topup(&mut self, address: Address, topup: U256) -> ExecutionResult<()> {
        let account = match self.accounts.remove(&address) {
            Some(Account::Full {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
                appending_logs: appending_logs,
            }) => {
                Account::Full {
                    address: address,
                    balance: balance + topup,
                    storage: storage,
                    code: code,
                    appending_logs: appending_logs,
                }
            },
            Some(Account::Code {
                ..
            }) => {
                return Err(ExecutionError::RequireAccount(address));
            }
            Some(Account::Remove(address)) => {
                Account::Full {
                    address: address,
                    balance: topup,
                    storage: S::default(),
                    code: Vec::new(),
                    appending_logs: Vec::new(),
                }
            },
            Some(Account::Topup(address, old_topup)) => {
                Account::Topup(address, old_topup + topup)
            },
            None => {
                Account::Topup(address, topup)
            },
        };
        self.accounts.insert(address, account);
        Ok(())
    }

    fn account_remove(&mut self, address: Address) {
        self.accounts.insert(address, Account::Remove(address));
    }

    fn account_storage(&self, address: Address) -> ExecutionResult<&S> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                storage: ref storage,
                ..
            }) => {
                Ok(storage)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn account_storage_mut(&mut self, address: Address) -> ExecutionResult<&mut S> {
        match self.accounts.get_mut(&address) {
            Some(&mut Account::Full {
                storage: ref mut storage,
                ..
            }) => {
                Ok(storage)
            },
            _ => {
                Err(ExecutionError::RequireAccount(address))
            }
        }
    }

    fn blockhash(&mut self, number: M256) -> ExecutionResult<M256> {
        match self.blockhashes.get(&number) {
            Some(val) => Ok(*val),
            None => Err(ExecutionError::RequireBlockhash(number)),
        }
    }

    pub fn peek_cost(&self) -> ExecutionResult<Gas> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        let opcode = self.pc.peek_opcode()?;
        let aggregrator = self.cost_aggregrator;
        let (gas, agg) = gas_cost(opcode, &self, aggregrator)?;
        Ok(gas)
    }

    pub fn step(&mut self) -> ExecutionResult<()> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        begin_rescuable!(self, &mut Self, __);
        if self.pc.stopped() {
            trr!(Err(ExecutionError::Stopped), __);
        }

        let position = self.pc.position();
        on_rescue!(|machine| {
            machine.pc.jump_unchecked(position);
        }, __);

        let opcode = trr!(self.pc.read_opcode(), __);
        let available_gas = self.available_gas();
        let cost_aggregrator = self.cost_aggregrator;
        let (gas, agg) = trr!(gas_cost(opcode, self, cost_aggregrator), __);
        let refunded = trr!(gas_refund(opcode, self), __);

        if gas > self.available_gas() {
            trr!(Err(ExecutionError::EmptyGas), __);
        }

        trr!(run_opcode(opcode, self, available_gas - gas), __);

        self.cost_aggregrator = agg;
        self.used_gas = self.used_gas + gas;
        self.refunded_gas = self.refunded_gas + refunded;

        end_rescuable!(__);
        Ok(())
    }

    pub fn fire(&mut self) -> ExecutionResult<()> {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {
                    ExecutionError::Stopped => return Ok(()),
                    err => return Err(err),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! See librustc_codegen_llvm/meth.rs for reference

use crate::prelude::*;

const DROP_FN_INDEX: usize = 0;
const SIZE_INDEX: usize = 1;
const ALIGN_INDEX: usize = 2;

pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (DROP_FN_INDEX * usize_size) as i32,
    )
}

pub fn size_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (SIZE_INDEX * usize_size) as i32,
    )
}

pub fn min_align_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (ALIGN_INDEX * usize_size) as i32,
    )
}

pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    arg: CValue<'tcx>,
    idx: usize,
) -> (Value, Value) {
    let arg = if arg.layout().ty.is_box() {
        // Cast `Box<T>` to `*mut T` so `load_value_pair` works
        arg.unchecked_cast_to(fx.layout_of(fx.tcx.mk_mut_ptr(arg.layout().ty.boxed_ty())))
    } else {
        arg
    };

    let (ptr, vtable) = arg.load_value_pair(fx);
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
    let func_ref = fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        ((idx + 3) * usize_size as usize) as i32,
    );
    (ptr, func_ref)
}

pub fn get_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
    let data_id = if let Some(data_id) = fx.caches.vtables.get(&(ty, trait_ref)) {
        *data_id
    } else {
        let data_id = build_vtable(fx, ty, trait_ref);
        fx.caches.vtables.insert((ty, trait_ref), data_id);
        data_id
    };

    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}

fn build_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> DataId {
    let tcx = fx.tcx;
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;

    let drop_in_place_fn = import_function(
        tcx,
        fx.module,
        crate::rustc_mir::monomorphize::resolve_drop_in_place(tcx, ty),
    );

    let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];

    let methods_root;
    let methods = if let Some(trait_ref) = trait_ref {
        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
        methods_root.iter()
    } else {
        (&[]).iter()
    };
    let methods = methods.cloned().map(|opt_mth| {
        opt_mth.map_or(None, |(def_id, substs)| {
            Some(import_function(
                tcx,
                fx.module,
                Instance::resolve(tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            ))
        })
    });
    components.extend(methods);

    let mut data_ctx = DataContext::new();
    let mut data = ::std::iter::repeat(0u8)
        .take(components.len() * usize_size)
        .collect::<Vec<u8>>()
        .into_boxed_slice();

    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
    write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
    write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
    data_ctx.define(data);

    for (i, component) in components.into_iter().enumerate() {
        if let Some(func_id) = component {
            let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
            data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
        }
    }

    let data_id = fx
        .module
        .declare_data(
            &format!("vtable.{:?}.for.{:?}", trait_ref, ty),
            Linkage::Local,
            false,
        )
        .unwrap();
    fx.module.define_data(data_id, &data_ctx).unwrap();
    data_id
}

fn write_usize(tcx: TyCtxt, buf: &mut [u8], idx: usize, num: u64) {
    use byteorder::{BigEndian, LittleEndian, WriteBytesExt};

    let usize_size = tcx
        .layout_of(ParamEnv::reveal_all().and(tcx.types.usize))
        .unwrap()
        .size
        .bytes() as usize;
    let mut target = &mut buf[idx * usize_size..(idx + 1) * usize_size];

    match tcx.data_layout.endian {
        layout::Endian::Little => target.write_uint::<LittleEndian>(num, usize_size),
        layout::Endian::Big => target.write_uint::<BigEndian>(num, usize_size),
    }
    .unwrap()
}
<commit_msg>Use Instance::resolve_for_vtable instead of Instance::resolve for vtables<commit_after>//! See librustc_codegen_llvm/meth.rs for reference

use crate::prelude::*;

const DROP_FN_INDEX: usize = 0;
const SIZE_INDEX: usize = 1;
const ALIGN_INDEX: usize = 2;

pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (DROP_FN_INDEX * usize_size) as i32,
    )
}

pub fn size_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (SIZE_INDEX * usize_size) as i32,
    )
}

pub fn min_align_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (ALIGN_INDEX * usize_size) as i32,
    )
}

pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    arg: CValue<'tcx>,
    idx: usize,
) -> (Value, Value) {
    let arg = if arg.layout().ty.is_box() {
        // Cast `Box<T>` to `*mut T` so `load_value_pair` works
        arg.unchecked_cast_to(fx.layout_of(fx.tcx.mk_mut_ptr(arg.layout().ty.boxed_ty())))
    } else {
        arg
    };

    let (ptr, vtable) = arg.load_value_pair(fx);
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
    let func_ref = fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        ((idx + 3) * usize_size as usize) as i32,
    );
    (ptr, func_ref)
}

pub fn get_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
    let data_id = if let Some(data_id) = fx.caches.vtables.get(&(ty, trait_ref)) {
        *data_id
    } else {
        let data_id = build_vtable(fx, ty, trait_ref);
        fx.caches.vtables.insert((ty, trait_ref), data_id);
        data_id
    };

    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}

fn build_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> DataId {
    let tcx = fx.tcx;
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;

    let drop_in_place_fn = import_function(
        tcx,
        fx.module,
        crate::rustc_mir::monomorphize::resolve_drop_in_place(tcx, ty),
    );

    let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];

    let methods_root;
    let methods = if let Some(trait_ref) = trait_ref {
        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
        methods_root.iter()
    } else {
        (&[]).iter()
    };
    let methods = methods.cloned().map(|opt_mth| {
        opt_mth.map_or(None, |(def_id, substs)| {
            Some(import_function(
                tcx,
                fx.module,
                Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            ))
        })
    });
    components.extend(methods);

    let mut data_ctx = DataContext::new();
    let mut data = ::std::iter::repeat(0u8)
        .take(components.len() * usize_size)
        .collect::<Vec<u8>>()
        .into_boxed_slice();

    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
    write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
    write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
    data_ctx.define(data);

    for (i, component) in components.into_iter().enumerate() {
        if let Some(func_id) = component {
            let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
            data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
        }
    }

    let data_id = fx
        .module
        .declare_data(
            &format!("vtable.{:?}.for.{:?}", trait_ref, ty),
            Linkage::Local,
            false,
        )
        .unwrap();
    fx.module.define_data(data_id, &data_ctx).unwrap();
    data_id
}

fn write_usize(tcx: TyCtxt, buf: &mut [u8], idx: usize, num: u64) {
    use byteorder::{BigEndian, LittleEndian, WriteBytesExt};

    let usize_size = tcx
        .layout_of(ParamEnv::reveal_all().and(tcx.types.usize))
        .unwrap()
        .size
        .bytes() as usize;
    let mut target = &mut buf[idx * usize_size..(idx + 1) * usize_size];

    match tcx.data_layout.endian {
        layout::Endian::Little => target.write_uint::<LittleEndian>(num, usize_size),
        layout::Endian::Big => target.write_uint::<BigEndian>(num, usize_size),
    }
    .unwrap()
}
<|endoftext|>


<commit_before>//! See librustc_codegen_llvm/meth.rs for reference

use crate::prelude::*;

const DROP_FN_INDEX: usize = 0;
const SIZE_INDEX: usize = 1;
const ALIGN_INDEX: usize = 2;

pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (DROP_FN_INDEX * usize_size) as i32,
    )
}

pub fn size_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (SIZE_INDEX * usize_size) as i32,
    )
}

pub fn min_align_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (ALIGN_INDEX * usize_size) as i32,
    )
}

pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    arg: CValue<'tcx>,
    idx: usize,
) -> (Value, Value) {
    let (ptr, vtable) = arg.load_scalar_pair(fx);
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
    let func_ref = fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        ((idx + 3) * usize_size as usize) as i32,
    );
    (ptr, func_ref)
}

pub fn get_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
    let data_id = if let Some(data_id) = fx.caches.vtables.get(&(ty, trait_ref)) {
        *data_id
    } else {
        let data_id = build_vtable(fx, ty, trait_ref);
        fx.caches.vtables.insert((ty, trait_ref), data_id);
        data_id
    };

    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}

fn build_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> DataId {
    let tcx = fx.tcx;
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;

    let drop_in_place_fn = import_function(
        tcx,
        fx.module,
        crate::rustc_mir::monomorphize::resolve_drop_in_place(tcx, ty),
    );

    let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];

    let methods_root;
    let methods = if let Some(trait_ref) = trait_ref {
        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
        methods_root.iter()
    } else {
        (&[]).iter()
    };
    let methods = methods.cloned().map(|opt_mth| {
        opt_mth.map_or(None, |(def_id, substs)| {
            Some(import_function(
                tcx,
                fx.module,
                Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            ))
        })
    });
    components.extend(methods);

    let mut data_ctx = DataContext::new();
    let mut data = ::std::iter::repeat(0u8)
        .take(components.len() * usize_size)
        .collect::<Vec<u8>>()
        .into_boxed_slice();

    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
    write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
    write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
    data_ctx.define(data);

    for (i, component) in components.into_iter().enumerate() {
        if let Some(func_id) = component {
            let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
            data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
        }
    }

    let data_id = fx
        .module
        .declare_data(
            &format!("vtable.{:?}.for.{:?}", trait_ref, ty),
            Linkage::Local,
            false,
        )
        .unwrap();
    fx.module.define_data(data_id, &data_ctx).unwrap();
    data_id
}

fn write_usize(tcx: TyCtxt, buf: &mut [u8], idx: usize, num: u64) {
    use byteorder::{BigEndian, LittleEndian, WriteBytesExt};

    let usize_size = tcx
        .layout_of(ParamEnv::reveal_all().and(tcx.types.usize))
        .unwrap()
        .size
        .bytes() as usize;
    let mut target = &mut buf[idx * usize_size..(idx + 1) * usize_size];

    match tcx.data_layout.endian {
        layout::Endian::Little => target.write_uint::<LittleEndian>(num, usize_size),
        layout::Endian::Big => target.write_uint::<BigEndian>(num, usize_size),
    }
    .unwrap()
}
<commit_msg>Fix using using the same vtable twice<commit_after>//! See librustc_codegen_llvm/meth.rs for reference

use crate::prelude::*;

const DROP_FN_INDEX: usize = 0;
const SIZE_INDEX: usize = 1;
const ALIGN_INDEX: usize = 2;

pub fn drop_fn_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (DROP_FN_INDEX * usize_size) as i32,
    )
}

pub fn size_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (SIZE_INDEX * usize_size) as i32,
    )
}

pub fn min_align_of_obj<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    vtable: Value,
) -> Value {
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
    fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        (ALIGN_INDEX * usize_size) as i32,
    )
}

pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    arg: CValue<'tcx>,
    idx: usize,
) -> (Value, Value) {
    let (ptr, vtable) = arg.load_scalar_pair(fx);
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
    let func_ref = fx.bcx.ins().load(
        pointer_ty(fx.tcx),
        MemFlags::new(),
        vtable,
        ((idx + 3) * usize_size as usize) as i32,
    );
    (ptr, func_ref)
}

pub fn get_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
    let data_id = if let Some(data_id) = fx.caches.vtables.get(&(ty, trait_ref)) {
        *data_id
    } else {
        let data_id = build_vtable(fx, ty, trait_ref);
        fx.caches.vtables.insert((ty, trait_ref), data_id);
        data_id
    };

    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
    fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}

fn build_vtable<'a, 'tcx: 'a>(
    fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
    ty: Ty<'tcx>,
    trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> DataId {
    let tcx = fx.tcx;
    let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;

    let drop_in_place_fn = import_function(
        tcx,
        fx.module,
        crate::rustc_mir::monomorphize::resolve_drop_in_place(tcx, ty),
    );

    let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];

    let methods_root;
    let methods = if let Some(trait_ref) = trait_ref {
        methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
        methods_root.iter()
    } else {
        (&[]).iter()
    };
    let methods = methods.cloned().map(|opt_mth| {
        opt_mth.map_or(None, |(def_id, substs)| {
            Some(import_function(
                tcx,
                fx.module,
                Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs).unwrap(),
            ))
        })
    });
    components.extend(methods);

    let mut data_ctx = DataContext::new();
    let mut data = ::std::iter::repeat(0u8)
        .take(components.len() * usize_size)
        .collect::<Vec<u8>>()
        .into_boxed_slice();

    let layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
    write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
    write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
    data_ctx.define(data);

    for (i, component) in components.into_iter().enumerate() {
        if let Some(func_id) = component {
            let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
            data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
        }
    }

    let data_id = fx
        .module
        .declare_data(
            &format!("vtable.{:?}.for.{:?}", trait_ref, ty),
            Linkage::Local,
            false,
        )
        .unwrap();

    match fx.module.define_data(data_id, &data_ctx) {
        Ok(()) | Err(cranelift_module::ModuleError::DuplicateDefinition(_)) => {}
        err => err.unwrap(),
    }

    data_id
}

fn write_usize(tcx: TyCtxt, buf: &mut [u8], idx: usize, num: u64) {
    use byteorder::{BigEndian, LittleEndian, WriteBytesExt};

    let usize_size = tcx
        .layout_of(ParamEnv::reveal_all().and(tcx.types.usize))
        .unwrap()
        .size
        .bytes() as usize;
    let mut target = &mut buf[idx * usize_size..(idx + 1) * usize_size];

    match tcx.data_layout.endian {
        layout::Endian::Little => target.write_uint::<LittleEndian>(num, usize_size),
        layout::Endian::Big => target.write_uint::<BigEndian>(num, usize_size),
    }
    .unwrap()
}
<|endoftext|>


<commit_before>use std::io::Read;

use crate::common::LineIter;

fn parse_bit(bit: char) -> usize {
    if bit == '1' {
        1
    } else {
        0
    }
}

pub fn part1(input: &mut dyn Read) -> String {
    let mut reader = LineIter::new(input);

    let mut totals: Vec<usize> = reader.next().unwrap().chars().map(parse_bit).collect();

    let mut count = 1;

    while let Some(line) = reader.next() {
        line.chars()
            .map(parse_bit)
            .zip(totals.iter_mut())
            .for_each(|(b, t)| *t += b);

        count += 1;
    }

    let bitmask = (1 << totals.len()) - 1;

    let gamma = totals.into_iter().fold(0, |mut current, total| {
        current <<= 1;
        if total > count / 2 {
            current |= 1;
        };

        current
    });

    let epsilon = (!gamma) & bitmask;

    (gamma * epsilon).to_string()
}

fn find_remaining(mut strings: Vec<u32>, most: bool, len: usize) -> u32 {
    for pos in 1..=len {
        if strings.len() == 1 {
            break;
        }

        let bit = 1 << (len - pos);

        let occurrences = strings.iter().filter(|&&b| (b & bit) == bit).count();

        let keep = if (occurrences * 2 < strings.len()) ^ most {
            bit
        } else {
            0
        };

        strings.retain(|&b| (b & bit) == keep);
    }

    strings[0]
}

pub fn part2(input: &mut dyn Read) -> String {
    let mut strings = Vec::new();
    let mut reader = LineIter::new(input);
    let mut len = None;

    while let Some(line) = reader.next() {
        strings.push(u32::from_str_radix(line, 2).unwrap());
        len = Some(line.len());
    }

    let len = len.unwrap();

    let oxygen = find_remaining(strings.clone(), true, len);
    let co2 = find_remaining(strings, false, len);

    (oxygen * co2).to_string()
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = include_bytes!("samples/03.txt");

    #[test]
    fn sample_part1() {
        test_implementation(part1, SAMPLE, 198);
    }

    #[test]
    fn sample_part2() {
        test_implementation(part2, SAMPLE, 230)
    }
}
<commit_msg>Less awkward line length hack<commit_after>use std::io::Read;

use crate::common::LineIter;

fn parse_bit(bit: char) -> usize {
    if bit == '1' {
        1
    } else {
        0
    }
}

pub fn part1(input: &mut dyn Read) -> String {
    let mut reader = LineIter::new(input);

    let mut totals: Vec<usize> = reader.next().unwrap().chars().map(parse_bit).collect();

    let mut count = 1;

    while let Some(line) = reader.next() {
        line.chars()
            .map(parse_bit)
            .zip(totals.iter_mut())
            .for_each(|(b, t)| *t += b);

        count += 1;
    }

    let bitmask = (1 << totals.len()) - 1;

    let gamma = totals.into_iter().fold(0, |mut current, total| {
        current <<= 1;
        if total > count / 2 {
            current |= 1;
        };

        current
    });

    let epsilon = (!gamma) & bitmask;

    (gamma * epsilon).to_string()
}

fn find_remaining(mut strings: Vec<u32>, most: bool, len: usize) -> u32 {
    for pos in 1..=len {
        if strings.len() == 1 {
            break;
        }

        let bit = 1 << (len - pos);

        let occurrences = strings.iter().filter(|&&b| (b & bit) == bit).count();

        let keep = if (occurrences * 2 < strings.len()) ^ most {
            bit
        } else {
            0
        };

        strings.retain(|&b| (b & bit) == keep);
    }

    strings[0]
}

pub fn part2(input: &mut dyn Read) -> String {
    let mut strings = Vec::new();
    let mut reader = LineIter::new(input);
    let mut read_line = reader.next();
    let len = read_line.unwrap().len();

    while let Some(line) = read_line {
        strings.push(u32::from_str_radix(line, 2).unwrap());
        read_line = reader.next();
    }

    let oxygen = find_remaining(strings.clone(), true, len);
    let co2 = find_remaining(strings, false, len);

    (oxygen * co2).to_string()
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = include_bytes!("samples/03.txt");

    #[test]
    fn sample_part1() {
        test_implementation(part1, SAMPLE, 198);
    }

    #[test]
    fn sample_part2() {
        test_implementation(part2, SAMPLE, 230)
    }
}
<|endoftext|>