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

//! Note that this is NOT Ken Perlin's simplex noise, as that is patent encumbered.
//! Instead, these functions use the OpenSimplex algorithm, as detailed here:
//! http://uniblock.tumblr.com/post/97868843242/noise

use num::Float;

use {gradient, math, Seed};

const STRETCH_CONSTANT_2D: f64 = -0.211324865405187; //(1/sqrt(2+1)-1)/2;
const SQUISH_CONSTANT_2D: f64 = 0.366025403784439; //(sqrt(2+1)-1)/2;
const STRETCH_CONSTANT_3D: f64 = -1.0 / 6.0; //(1/Math.sqrt(3+1)-1)/3;
const SQUISH_CONSTANT_3D: f64 = 1.0 / 3.0; //(Math.sqrt(3+1)-1)/3;

const NORM_CONSTANT_2D: f32 = 1.0 / 14.0;
const NORM_CONSTANT_3D: f32 = 1.0 / 14.0;

/// 2-dimensional [OpenSimplex Noise](http://uniblock.tumblr.com/post/97868843242/noise)
///
/// This is a slower but higher quality form of gradient noise than `noise::perlin2`.
pub fn open_simplex2<T: Float>(seed: &Seed, point: &::Point2<T>) -> T {
    fn gradient<T: Float>(seed: &Seed, xs_floor: T, ys_floor: T, dx: T, dy: T) -> T {
        let zero: T = math::cast(0);

        let attn = math::cast::<_, T>(2.0_f64) - dx * dx - dy * dy;
        if attn > zero {
            let index = seed.get2::<isize>([math::cast(xs_floor), math::cast(ys_floor)]);
            let vec = gradient::get2::<T>(index);
            math::pow4(attn) * (dx * vec[0] + dy * vec[1])
        } else {
            zero
        }
    }

    let zero: T = math::cast(0);
    let one: T = math::cast(1);
    let two: T = math::cast(2);
    let squish_constant: T = math::cast(SQUISH_CONSTANT_2D);

    //Place input coordinates onto grid.
    let stretch_offset = (point[0] + point[1]) * math::cast(STRETCH_CONSTANT_2D);
    let xs = point[0] + stretch_offset;
    let ys = point[1] + stretch_offset;

    //Floor to get grid coordinates of rhombus (stretched square) super-cell origin.
    let mut xs_floor = xs.floor();
    let mut ys_floor = ys.floor();

    //Skew out to get actual coordinates of rhombus origin. We'll need these later.
    let squish_offset = (xs_floor + ys_floor) * squish_constant;
    let x_floor = xs_floor + squish_offset;
    let y_floor = ys_floor + squish_offset;

    //Compute grid coordinates relative to rhombus origin.
    let xs_frac = xs - xs_floor;
    let ys_frac = ys - ys_floor;

    //Sum those together to get a value that determines which region we're in.
    let frac_sum = xs_frac + ys_frac;

    //Positions relative to origin point.
    let mut dx0 = point[0] - x_floor;
    let mut dy0 = point[1] - y_floor;

    let mut value: T = zero;

    //Contribution (1,0)
    let dx1 = dx0 - one - squish_constant;
    let dy1 = dy0 - zero - squish_constant;
    value = value + gradient(seed, xs_floor + one, ys_floor + zero, dx1, dy1);

    //Contribution (0,1)
    let dx2 = dx0 - zero - squish_constant;
    let dy2 = dy0 - one - squish_constant;
    value = value + gradient(seed, xs_floor + zero, ys_floor + one, dx2, dy2);

    if frac_sum > one {
        xs_floor = xs_floor + one;
        ys_floor = ys_floor + one;
        dx0 = dx0 - one - two * squish_constant;
        dy0 = dy0 - one - two * squish_constant;
    }

    //Contribution (0,0) or (1,1)
    value = value + gradient(seed, xs_floor, ys_floor, dx0, dy0);

    value * math::cast(NORM_CONSTANT_2D)
}

/// 3-dimensional [OpenSimplex Noise](http://uniblock.tumblr.com/post/97868843242/noise)
///
/// This is a slower but higher quality form of gradient noise than `noise::perlin3`.
pub fn open_simplex3<T: Float>(seed: &Seed, point: &::Point3<T>) -> T {
    fn gradient<T: Float>(seed: &Seed, xs_floor: T, ys_floor: T, zs_floor: T, dx: T, dy: T, dz: T) -> T {
        let zero: T = math::cast(0);

        let attn = math::cast::<_, T>(2.0_f64) - dx * dx - dy * dy - dz * dz;
        if attn > zero {
            let index = seed.get3::<isize>([math::cast(xs_floor), math::cast(ys_floor), math::cast(zs_floor)]);
            let vec = gradient::get3::<T>(index);
            math::pow4(attn) * (dx * vec[0] + dy * vec[1] + dz * vec[2])
        } else {
            zero
        }
    }

    let zero: T = math::cast(0);
    let one: T = math::cast(1);
    let two: T = math::cast(2);
    let three: T = math::cast(3);
    let squish_constant: T = math::cast(SQUISH_CONSTANT_3D);

    //Place input coordinates on simplectic honeycomb.
    let stretch_offset = (point[0] + point[1] + point[2]) * math::cast(STRETCH_CONSTANT_3D);
    let xs = point[0] + stretch_offset;
    let ys = point[1] + stretch_offset;
    let zs = point[2] + stretch_offset;

    //Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin.
    let xsb = xs.floor();
    let ysb = ys.floor();
    let zsb = zs.floor();

    //Skew out to get actual coordinates of rhombohedron origin. We'll need these later.
    let squish_offset = (xsb + ysb + zsb) * squish_constant;
    let xb = xsb + squish_offset;
    let yb = ysb + squish_offset;
    let zb = zsb + squish_offset;

    //Compute simplectic honeycomb coordinates relative to rhombohedral origin.
    let xins = xs - xsb;
    let yins = ys - ysb;
    let zins = zs - zsb;

    //Sum those together to get a value that determines which region we're in.
    let in_sum = xins + yins + zins;

    //Positions relative to origin point.
    let mut dx0 = point[0] - xb;
    let mut dy0 = point[1] - yb;
    let mut dz0 = point[2] - zb;

    let mut value = zero;
    if in_sum <= one { //We're inside the tetrahedron (3-Simplex) at (0,0,0)
        //Contribution (0,0,0)
        value = value + gradient(seed, xsb, ysb, zsb, dx0, dy0, dz0);

        //Contribution (1,0,0)
        let dx1 = dx0 - one - squish_constant;
        let dy1 = dy0 - zero - squish_constant;
        let dz1 = dz0 - zero - squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb, dx1, dy1, dz1);

        //Contribution (0,1,0)
        let dx2 = dx0 - zero - squish_constant;
        let dy2 = dy0 - one - squish_constant;
        let dz2 = dz1;
        value = value + gradient(seed, xsb, ysb + one, zsb, dx2, dy2, dz2);

        //Contribution (0,0,1)
        let dx3 = dx2;
        let dy3 = dy1;
        let dz3 = dz0 - one - squish_constant;
        value = value + gradient(seed, xsb, ysb, zsb + one, dx3, dy3, dz3);
    } else if in_sum >= two { //We're inside the tetrahedron (3-Simplex) at (1,11)
        //Contribution (1,1,0)
        let dx3 = dx0 - one - two * squish_constant;
        let dy3 = dy0 - one - two * squish_constant;
        let dz3 = dz0 - zero - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb, dx3, dy3, dz3);

        //Contribution (1,0,1)
        let dx2 = dx3;
        let dy2 = dy0 - zero - two * squish_constant;
        let dz2 = dz0 - one - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb + one, dx2, dy2, dz2);

        //Contribution (0,1,1)
        let dx1 = dx0 - zero - two * squish_constant;
        let dy1 = dy3;
        let dz1 = dz2;
        value = value + gradient(seed, xsb, ysb + one, zsb + one, dx1, dy1, dz1);

        //Contribution (1,1,1)
        dx0 = dx0 - one - three * squish_constant;
        dy0 = dy0 - one - three * squish_constant;
        dz0 = dz0 - one - three * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb + one, dx0, dy0, dz0);
    } else { //We're inside the octahedron (Rectified 3-Simplex) in between.
        //Contribution (1,0,0)
        let dx1 = dx0 - one - squish_constant;
        let dy1 = dy0 - zero - squish_constant;
        let dz1 = dz0 - zero - squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb, dx1, dy1, dz1);

        //Contribution (0,1,0)
        let dx2 = dx0 - zero - squish_constant;
        let dy2 = dy0 - one - squish_constant;
        let dz2 = dz1;
        value = value + gradient(seed, xsb, ysb + one, zsb, dx2, dy2, dz2);

        //Contribution (0,0,1)
        let dx3 = dx2;
        let dy3 = dy1;
        let dz3 = dz0 - one - squish_constant;
        value = value + gradient(seed, xsb, ysb, zsb + one, dx3, dy3, dz3);

        //Contribution (1,1,0)
        let dx4 = dx0 - one - two * squish_constant;
        let dy4 = dy0 - one - two * squish_constant;
        let dz4 = dz0 - zero - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb, dx4, dy4, dz4);

        //Contribution (1,0,1)
        let dx5 = dx4;
        let dy5 = dy0 - zero - two * squish_constant;
        let dz5 = dz0 - one - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb + one, dx5, dy5, dz5);

        //Contribution (0,1,1)
        let dx6 = dx0 - zero - two * squish_constant;
        let dy6 = dy4;
        let dz6 = dz5;
        value = value + gradient(seed, xsb, ysb + one, zsb + one, dx6, dy6, dz6);
    }

    return value * math::cast(NORM_CONSTANT_3D);
}
<commit_msg>Test open simplex optimization.<commit_after>// Copyright 2013 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Note that this is NOT Ken Perlin's simplex noise, as that is patent encumbered.
//! Instead, these functions use the OpenSimplex algorithm, as detailed here:
//! http://uniblock.tumblr.com/post/97868843242/noise

use num::Float;

use {gradient, math, Seed};

const STRETCH_CONSTANT_2D: f64 = -0.211324865405187; //(1/sqrt(2+1)-1)/2;
const SQUISH_CONSTANT_2D: f64 = 0.366025403784439; //(sqrt(2+1)-1)/2;
const STRETCH_CONSTANT_3D: f64 = -1.0 / 6.0; //(1/Math.sqrt(3+1)-1)/3;
const SQUISH_CONSTANT_3D: f64 = 1.0 / 3.0; //(Math.sqrt(3+1)-1)/3;

const NORM_CONSTANT_2D: f32 = 1.0 / 14.0;
const NORM_CONSTANT_3D: f32 = 1.0 / 14.0;

/// 2-dimensional [OpenSimplex Noise](http://uniblock.tumblr.com/post/97868843242/noise)
///
/// This is a slower but higher quality form of gradient noise than `noise::perlin2`.
pub fn open_simplex2<T: Float>(seed: &Seed, point: &::Point2<T>) -> T {
    fn gradient<T: Float>(seed: &Seed, xs_floor: T, ys_floor: T, dx: T, dy: T) -> T {
        let zero: T = math::cast(0);

        let attn = math::cast::<_, T>(2.0_f64) - dx * dx - dy * dy;
        if attn > zero {
            let index = seed.get2::<isize>([math::cast(xs_floor), math::cast(ys_floor)]);
            let vec = gradient::get2::<T>(index);
            math::pow4(attn) * (dx * vec[0] + dy * vec[1])
        } else {
            zero
        }
    }

    let zero: T = math::cast(0);
    let one: T = math::cast(1);
    let two: T = math::cast(2);
    let squish_constant: T = math::cast(SQUISH_CONSTANT_2D);

    //Place input coordinates onto grid.
    let stretch_offset = (point[0] + point[1]) * math::cast(STRETCH_CONSTANT_2D);
    let xs = point[0] + stretch_offset;
    let ys = point[1] + stretch_offset;

    //Floor to get grid coordinates of rhombus (stretched square) super-cell origin.
    let mut xs_floor = xs.floor();
    let mut ys_floor = ys.floor();

    //Skew out to get actual coordinates of rhombus origin. We'll need these later.
    let squish_offset = (xs_floor + ys_floor) * squish_constant;
    let x_floor = xs_floor + squish_offset;
    let y_floor = ys_floor + squish_offset;

    //Compute grid coordinates relative to rhombus origin.
    let xs_frac = xs - xs_floor;
    let ys_frac = ys - ys_floor;

    //Sum those together to get a value that determines which region we're in.
    let frac_sum = xs_frac + ys_frac;

    //Positions relative to origin point.
    let mut dx0 = point[0] - x_floor;
    let mut dy0 = point[1] - y_floor;

    let mut value: T = zero;

    //Contribution (1,0)
    let dx1 = dx0 - one - squish_constant;
    let dy1 = dy0 - zero - squish_constant;
    value = value + gradient(seed, xs_floor + one, ys_floor + zero, dx1, dy1);

    //Contribution (0,1)
    let dx2 = dx1 + one;
    let dy2 = dy1 - one;
    value = value + gradient(seed, xs_floor + zero, ys_floor + one, dx2, dy2);

    if frac_sum > one {
        xs_floor = xs_floor + one;
        ys_floor = ys_floor + one;
        let t = one + two * squish_constant;
        dx0 = dx0 - t;
        dy0 = dy0 - t;
    }

    //Contribution (0,0) or (1,1)
    value = value + gradient(seed, xs_floor, ys_floor, dx0, dy0);

    value * math::cast(NORM_CONSTANT_2D)
}

/// 3-dimensional [OpenSimplex Noise](http://uniblock.tumblr.com/post/97868843242/noise)
///
/// This is a slower but higher quality form of gradient noise than `noise::perlin3`.
pub fn open_simplex3<T: Float>(seed: &Seed, point: &::Point3<T>) -> T {
    fn gradient<T: Float>(seed: &Seed, xs_floor: T, ys_floor: T, zs_floor: T, dx: T, dy: T, dz: T) -> T {
        let zero: T = math::cast(0);

        let attn = math::cast::<_, T>(2.0_f64) - dx * dx - dy * dy - dz * dz;
        if attn > zero {
            let index = seed.get3::<isize>([math::cast(xs_floor), math::cast(ys_floor), math::cast(zs_floor)]);
            let vec = gradient::get3::<T>(index);
            math::pow4(attn) * (dx * vec[0] + dy * vec[1] + dz * vec[2])
        } else {
            zero
        }
    }

    let zero: T = math::cast(0);
    let one: T = math::cast(1);
    let two: T = math::cast(2);
    let three: T = math::cast(3);
    let squish_constant: T = math::cast(SQUISH_CONSTANT_3D);

    //Place input coordinates on simplectic honeycomb.
    let stretch_offset = (point[0] + point[1] + point[2]) * math::cast(STRETCH_CONSTANT_3D);
    let xs = point[0] + stretch_offset;
    let ys = point[1] + stretch_offset;
    let zs = point[2] + stretch_offset;

    //Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin.
    let xsb = xs.floor();
    let ysb = ys.floor();
    let zsb = zs.floor();

    //Skew out to get actual coordinates of rhombohedron origin. We'll need these later.
    let squish_offset = (xsb + ysb + zsb) * squish_constant;
    let xb = xsb + squish_offset;
    let yb = ysb + squish_offset;
    let zb = zsb + squish_offset;

    //Compute simplectic honeycomb coordinates relative to rhombohedral origin.
    let xins = xs - xsb;
    let yins = ys - ysb;
    let zins = zs - zsb;

    //Sum those together to get a value that determines which region we're in.
    let in_sum = xins + yins + zins;

    //Positions relative to origin point.
    let mut dx0 = point[0] - xb;
    let mut dy0 = point[1] - yb;
    let mut dz0 = point[2] - zb;

    let mut value = zero;
    if in_sum <= one { //We're inside the tetrahedron (3-Simplex) at (0,0,0)
        //Contribution (0,0,0)
        value = value + gradient(seed, xsb, ysb, zsb, dx0, dy0, dz0);

        //Contribution (1,0,0)
        let dx1 = dx0 - one - squish_constant;
        let dy1 = dy0 - zero - squish_constant;
        let dz1 = dz0 - zero - squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb, dx1, dy1, dz1);

        //Contribution (0,1,0)
        let dx2 = dx0 - zero - squish_constant;
        let dy2 = dy0 - one - squish_constant;
        let dz2 = dz1;
        value = value + gradient(seed, xsb, ysb + one, zsb, dx2, dy2, dz2);

        //Contribution (0,0,1)
        let dx3 = dx2;
        let dy3 = dy1;
        let dz3 = dz0 - one - squish_constant;
        value = value + gradient(seed, xsb, ysb, zsb + one, dx3, dy3, dz3);
    } else if in_sum >= two { //We're inside the tetrahedron (3-Simplex) at (1,11)
        //Contribution (1,1,0)
        let dx3 = dx0 - one - two * squish_constant;
        let dy3 = dy0 - one - two * squish_constant;
        let dz3 = dz0 - zero - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb, dx3, dy3, dz3);

        //Contribution (1,0,1)
        let dx2 = dx3;
        let dy2 = dy0 - zero - two * squish_constant;
        let dz2 = dz0 - one - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb + one, dx2, dy2, dz2);

        //Contribution (0,1,1)
        let dx1 = dx0 - zero - two * squish_constant;
        let dy1 = dy3;
        let dz1 = dz2;
        value = value + gradient(seed, xsb, ysb + one, zsb + one, dx1, dy1, dz1);

        //Contribution (1,1,1)
        dx0 = dx0 - one - three * squish_constant;
        dy0 = dy0 - one - three * squish_constant;
        dz0 = dz0 - one - three * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb + one, dx0, dy0, dz0);
    } else { //We're inside the octahedron (Rectified 3-Simplex) in between.
        //Contribution (1,0,0)
        let dx1 = dx0 - one - squish_constant;
        let dy1 = dy0 - zero - squish_constant;
        let dz1 = dz0 - zero - squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb, dx1, dy1, dz1);

        //Contribution (0,1,0)
        let dx2 = dx0 - zero - squish_constant;
        let dy2 = dy0 - one - squish_constant;
        let dz2 = dz1;
        value = value + gradient(seed, xsb, ysb + one, zsb, dx2, dy2, dz2);

        //Contribution (0,0,1)
        let dx3 = dx2;
        let dy3 = dy1;
        let dz3 = dz0 - one - squish_constant;
        value = value + gradient(seed, xsb, ysb, zsb + one, dx3, dy3, dz3);

        //Contribution (1,1,0)
        let dx4 = dx0 - one - two * squish_constant;
        let dy4 = dy0 - one - two * squish_constant;
        let dz4 = dz0 - zero - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb + one, zsb, dx4, dy4, dz4);

        //Contribution (1,0,1)
        let dx5 = dx4;
        let dy5 = dy0 - zero - two * squish_constant;
        let dz5 = dz0 - one - two * squish_constant;
        value = value + gradient(seed, xsb + one, ysb, zsb + one, dx5, dy5, dz5);

        //Contribution (0,1,1)
        let dx6 = dx0 - zero - two * squish_constant;
        let dy6 = dy4;
        let dz6 = dz5;
        value = value + gradient(seed, xsb, ysb + one, zsb + one, dx6, dy6, dz6);
    }

    return value * math::cast(NORM_CONSTANT_3D);
}
<|endoftext|>


<commit_before>struct StringStream {
    input: Vec<char>,
    index: usize,
    line: i32,
    column: i32,
}

impl StringStream {
    fn new(input: &str) -> Self {
        Self {
            input: input.chars().collect(),
            index: 0,
            line: 1,
            column: 1,
        }
    }

    fn read(&mut self) -> char {
        let character = self
            .input
            .get(self.index)
            .map(|value| *value)
            .unwrap_or('\0');
        self.index += 1;
        if character == '\n' {
            self.line += 1;
            self.column = 1;
        } else {
            self.column += 1;
        }
        character
    }

    fn peek(&self) -> char {
        self.input
            .get(self.index)
            .map(|value| *value)
            .unwrap_or('\0')
    }

    fn read_until(&mut self, target: char) {
        while self.peek() != target {
            let character = self.read();
            assert!(character != '\0');
        }
    }

    fn read_if_match(&mut self, target: &[char]) -> bool {
        // Bounds-check first!
        if (self.index + target.len()) > self.input.len() {
            return false;
        }
        let substr = &self.input[self.index..(target.len())];
        if substr != target {
            return false;
        }
        // Consume if they match.
        for _ in target {
            self.read();
        }
        true
    }
}

#[derive(Clone, Debug, PartialEq)]
enum Token {
    EOF,
    Identifier(String),
    Integer(i64),
    Let,
    Func,
    Var,
    Return,
}

struct TokenStream {
    input: StringStream,
    peeking: bool,
    next_token: Option<Token>,
}

impl TokenStream {
    pub fn new(input: StringStream) -> Self {
        TokenStream {
            input: input,
            peeking: false,
            next_token: None,
        }
    }

    pub fn peek(&mut self) -> Token {
        if !self.peeking {
            self.peeking = true;
            self.next_token = Some(self.lex());
        }
        self.next_token.clone().unwrap()
    }

    pub fn read(&mut self) -> Token {
        let token = self.peek();
        self.peeking = false;
        return token;
    }

    fn lex(&mut self) -> Token {
        self.consume_space_and_comments();

        loop {
            let character = self.input.peek();

            if identifier_head(character) {
                return self.lex_identifier();
            } else if numeric_head(character) {
                return self.lex_numeric();
            } else {
                match character {
                    '\0' => return Token::EOF,
                    _ => panic!("Unexpected character: {}", character),
                }
            }
        }
    }

    fn lex_identifier(&mut self) -> Token {
        let mut identifier = vec![self.input.read()];
        loop {
            let character = self.input.peek();
            if identifier_tail(character) {
                self.input.read();
                identifier.push(character);
            } else {
                break;
            }
        }
        let identifier_string: String = identifier.into_iter().collect();
        match identifier_string.as_str() {
            "let" => Token::Let,
            "func" => Token::Func,
            "var" => Token::Var,
            "return" => Token::Return,
            _ => Token::Identifier(identifier_string),
        }
    }

    fn lex_numeric(&mut self) -> Token {
        let mut number = vec![self.input.read()];
        loop {
            let character = self.input.peek();
            if digit(character) {
                self.input.read();
                number.push(character);
            } else {
                break;
            }
        }
        let number_string: String = number.into_iter().collect();
        return Token::Integer(number_string.parse().unwrap());
    }

    fn consume_space_and_comments(&mut self) {
        loop {
            let character = self.input.peek();
            if character == ' ' || character == '\t' {
                self.input.read();
            } else if self.input.read_if_match(&['/', '/']) {
                self.input.read_until('\n');
            } else if self.input.read_if_match(&['/', '*']) {
                loop {
                    if self.input.read_if_match(&['*', '/']) {
                        break;
                    } else {
                        self.input.read();
                    }
                }
            } else {
                // Not any kind of comment.
                break;
            }
        }
    }
}

fn identifier_head(character: char) -> bool {
    alphabetical(character)
}

fn identifier_tail(character: char) -> bool {
    alphabetical(character)
}

fn numeric_head(character: char) -> bool {
    digit(character)
}

fn alphabetical(character: char) -> bool {
    (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z')
}

fn digit(character: char) -> bool {
    (character >= '0' && character <= '9')
}

#[cfg(test)]
mod tests {
    use super::{StringStream, Token, TokenStream};

    fn parse(input: &str) -> Vec<Token> {
        let string_stream = StringStream::new(input);
        let mut token_stream = TokenStream::new(string_stream);
        let mut tokens = vec![];
        loop {
            let token = token_stream.read();
            tokens.push(token.clone());
            if token == Token::EOF {
                break;
            }
        }
        return tokens;
    }

    #[test]
    fn it_parses_identifier() {
        assert_eq!(
            parse("foo"),
            vec![Token::Identifier("foo".to_string()), Token::EOF,]
        );
    }

    #[test]
    fn it_parses_keywords() {
        assert_eq!(parse("func"), vec![Token::Func, Token::EOF,]);
        assert_eq!(parse("let"), vec![Token::Let, Token::EOF,]);
        assert_eq!(parse("return"), vec![Token::Return, Token::EOF,]);
        assert_eq!(parse("var"), vec![Token::Var, Token::EOF,]);
    }
}
<commit_msg>Fix range slicing bug<commit_after>struct StringStream {
    input: Vec<char>,
    index: usize,
    line: i32,
    column: i32,
}

impl StringStream {
    fn new(input: &str) -> Self {
        Self {
            input: input.chars().collect(),
            index: 0,
            line: 1,
            column: 1,
        }
    }

    fn read(&mut self) -> char {
        let character = self
            .input
            .get(self.index)
            .map(|value| *value)
            .unwrap_or('\0');
        self.index += 1;
        if character == '\n' {
            self.line += 1;
            self.column = 1;
        } else {
            self.column += 1;
        }
        character
    }

    fn peek(&self) -> char {
        self.input
            .get(self.index)
            .map(|value| *value)
            .unwrap_or('\0')
    }

    fn read_until(&mut self, target: char) {
        while self.peek() != target {
            let character = self.read();
            assert!(character != '\0');
        }
    }

    fn read_if_match(&mut self, target: &[char]) -> bool {
        // Bounds-check first!
        if (self.index + target.len()) > self.input.len() {
            return false;
        }
        let substr = &self.input[self.index..(self.index + target.len())];
        if substr != target {
            return false;
        }
        // Consume if they match.
        for _ in target {
            self.read();
        }
        true
    }
}

#[derive(Clone, Debug, PartialEq)]
enum Token {
    EOF,
    Identifier(String),
    Integer(i64),
    Let,
    Func,
    Var,
    Return,
}

struct TokenStream {
    input: StringStream,
    peeking: bool,
    next_token: Option<Token>,
}

impl TokenStream {
    pub fn new(input: StringStream) -> Self {
        TokenStream {
            input: input,
            peeking: false,
            next_token: None,
        }
    }

    pub fn peek(&mut self) -> Token {
        if !self.peeking {
            self.peeking = true;
            self.next_token = Some(self.lex());
        }
        self.next_token.clone().unwrap()
    }

    pub fn read(&mut self) -> Token {
        let token = self.peek();
        self.peeking = false;
        return token;
    }

    fn lex(&mut self) -> Token {
        self.consume_space_and_comments();

        loop {
            let character = self.input.peek();

            if identifier_head(character) {
                return self.lex_identifier();
            } else if numeric_head(character) {
                return self.lex_numeric();
            } else {
                match character {
                    '\0' => return Token::EOF,
                    _ => panic!("Unexpected character: {}", character),
                }
            }
        }
    }

    fn lex_identifier(&mut self) -> Token {
        let mut identifier = vec![self.input.read()];
        loop {
            let character = self.input.peek();
            if identifier_tail(character) {
                self.input.read();
                identifier.push(character);
            } else {
                break;
            }
        }
        let identifier_string: String = identifier.into_iter().collect();
        match identifier_string.as_str() {
            "let" => Token::Let,
            "func" => Token::Func,
            "var" => Token::Var,
            "return" => Token::Return,
            _ => Token::Identifier(identifier_string),
        }
    }

    fn lex_numeric(&mut self) -> Token {
        let mut number = vec![self.input.read()];
        loop {
            let character = self.input.peek();
            if digit(character) {
                self.input.read();
                number.push(character);
            } else {
                break;
            }
        }
        let number_string: String = number.into_iter().collect();
        return Token::Integer(number_string.parse().unwrap());
    }

    fn consume_space_and_comments(&mut self) {
        loop {
            let character = self.input.peek();
            if character == ' ' || character == '\t' {
                self.input.read();
            } else if self.input.read_if_match(&['/', '/']) {
                self.input.read_until('\n');
            } else if self.input.read_if_match(&['/', '*']) {
                loop {
                    if self.input.read_if_match(&['*', '/']) {
                        break;
                    } else {
                        self.input.read();
                    }
                }
            } else {
                // Not any kind of comment.
                break;
            }
        }
    }
}

fn identifier_head(character: char) -> bool {
    alphabetical(character)
}

fn identifier_tail(character: char) -> bool {
    alphabetical(character)
}

fn numeric_head(character: char) -> bool {
    digit(character)
}

fn alphabetical(character: char) -> bool {
    (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z')
}

fn digit(character: char) -> bool {
    (character >= '0' && character <= '9')
}

#[cfg(test)]
mod tests {
    use super::{StringStream, Token, TokenStream};

    fn parse(input: &str) -> Vec<Token> {
        let string_stream = StringStream::new(input);
        let mut token_stream = TokenStream::new(string_stream);
        let mut tokens = vec![];
        loop {
            let token = token_stream.read();
            tokens.push(token.clone());
            if token == Token::EOF {
                break;
            }
        }
        return tokens;
    }

    #[test]
    fn it_parses_identifier() {
        assert_eq!(
            parse("foo"),
            vec![Token::Identifier("foo".to_string()), Token::EOF,]
        );
    }

    #[test]
    fn it_parses_keywords() {
        assert_eq!(parse("func"), vec![Token::Func, Token::EOF,]);
        assert_eq!(parse("let"), vec![Token::Let, Token::EOF,]);
        assert_eq!(parse("return"), vec![Token::Return, Token::EOF,]);
        assert_eq!(parse("var"), vec![Token::Var, Token::EOF,]);
    }
}
<|endoftext|>


<commit_before>use parser::combinators::{TypeWithLifetime, Str, Unit, Function, Parser, StrParser, Consumer, ParserConsumer, string, character};
use self::TokenAt::{LParen, RParen, Whitespace, Identifier};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum TokenAt<'a> {
    LParen,
    RParen,
    Whitespace,
    Identifier(&'a str),
}

pub struct Token;

impl<'a> TypeWithLifetime<'a> for Token {
    type Type = TokenAt<'a>;
}

impl Function<Unit,Token> for TokenAt<'static> {
    fn apply<'a>(&self, _: ()) -> TokenAt<'a> {
        self.clone()
    }
}

struct MkIdentifier;

impl Function<Str,Token> for MkIdentifier {
    fn apply<'a>(&self, name: &'a str) -> TokenAt<'a> {
        Identifier(name)
    }
}

#[allow(non_snake_case)]
pub fn lexer<C>(consumer: &mut C) where C: ParserConsumer<Str,Token> {
    let LPAREN = string("(").map(LParen);
    let RPAREN = string(")").map(RParen);
    let WHITESPACE = character(char::is_whitespace).plus().map(Whitespace);
    let IDENTIFIER = character(char::is_alphabetic).and_then(character(char::is_alphanumeric).star()).buffer().map(MkIdentifier);
    let TOKEN = LPAREN.or_else(RPAREN).or_else(WHITESPACE).or_else(IDENTIFIER);
    consumer.accept(TOKEN.star())
}

#[test]
fn test_lexer() {
    impl Consumer<Token> for Vec<TokenAt<'static>> {
        fn accept<'a>(&mut self, token: TokenAt<'a>) {
            assert_eq!(self.remove(0), token);
        }
    }
    struct TestConsumer;
    impl ParserConsumer<Str,Token> for TestConsumer {
        fn accept<P>(&mut self, mut lex: P) where P: Parser<Str,Token> {
            let mut tokens = vec![LParen, Identifier("a123"), Whitespace, Whitespace, Identifier("bcd"), RParen];
            lex.push_to("(a123  bcd)", &mut tokens);
            assert_eq!(tokens, []);
        }
    }
    lexer(&mut TestConsumer);
}
<commit_msg>Issue a Whitespace token for each whitespace char.<commit_after>use parser::combinators::{TypeWithLifetime, Str, Unit, Function, Parser, StrParser, Consumer, ParserConsumer, string, character};
use self::TokenAt::{LParen, RParen, Whitespace, Identifier};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum TokenAt<'a> {
    LParen,
    RParen,
    Whitespace,
    Identifier(&'a str),
}

pub struct Token;

impl<'a> TypeWithLifetime<'a> for Token {
    type Type = TokenAt<'a>;
}

impl Function<Unit,Token> for TokenAt<'static> {
    fn apply<'a>(&self, _: ()) -> TokenAt<'a> {
        self.clone()
    }
}

struct MkIdentifier;

impl Function<Str,Token> for MkIdentifier {
    fn apply<'a>(&self, name: &'a str) -> TokenAt<'a> {
        Identifier(name)
    }
}

#[allow(non_snake_case)]
pub fn lexer<C>(consumer: &mut C) where C: ParserConsumer<Str,Token> {
    let LPAREN = string("(").map(LParen);
    let RPAREN = string(")").map(RParen);
    let WHITESPACE = character(char::is_whitespace).map(Whitespace);
    let IDENTIFIER = character(char::is_alphabetic).and_then(character(char::is_alphanumeric).star()).buffer().map(MkIdentifier);
    let TOKEN = LPAREN.or_else(RPAREN).or_else(WHITESPACE).or_else(IDENTIFIER);
    consumer.accept(TOKEN.star())
}

#[test]
fn test_lexer() {
    impl Consumer<Token> for Vec<TokenAt<'static>> {
        fn accept<'a>(&mut self, token: TokenAt<'a>) {
            assert_eq!(self.remove(0), token);
        }
    }
    struct TestConsumer;
    impl ParserConsumer<Str,Token> for TestConsumer {
        fn accept<P>(&mut self, mut lex: P) where P: Parser<Str,Token> {
            let mut tokens = vec![LParen, Identifier("a123"), Whitespace, Whitespace, Identifier("bcd"), RParen];
            lex.push_to("(a123  bcd)", &mut tokens);
            assert_eq!(tokens, []);
        }
    }
    lexer(&mut TestConsumer);
}
<|endoftext|>


<commit_before>//! Atoms and atomic traits.

use std::{char, u8, u16, u32, u64, usize};
use std::{ascii, cmp};
use std::ops::Range;
use std::fmt::Debug;

use super::{Anchor, Element, Sequence, Repetition, Union};
use util::set::{self, Contains};

apply_attrs! {
    cfg(not(feature = "pattern_class")) => {
        /// Trait-bounds requirements for atomic values in a pattern.
        pub trait Atom: Debug + Copy + Clone + Eq + Ord {}
        impl<T> Atom for T where T: Debug + Copy + Clone + Eq + Ord {}
    },
    cfg(feature = "pattern_class") => {
        use super::Class;

        /// Trait-bounds requirements for atomic values in a pattern.
        pub trait Atom: Debug + Copy + Clone + Eq + Ord + Distance + Step {}
        impl<T> Atom for T where T: Debug + Copy + Clone + Eq + Ord + Distance + Step {}
    }
}

// Without the Distance + Step bounds on Atom, this impl conflicts with that
// for `RepeatCount`.
#[cfg(feature = "pattern_class")]
impl<T: Atom> set::IsSubsetOf<T> for T {
    #[inline(always)]
    fn is_subset_of(&self, other: &T) -> bool {
        self == other
    }
}

impl<T: Atom> set::IsSubsetOf<Anchor<T>> for T {
    /// An atom is never a subset of an anchor.
    #[inline(always)]
    fn is_subset_of(&self, _: &Anchor<T>) -> bool {
        false
    }
}

#[cfg(feature = "pattern_class")]
impl<T: Atom> set::IsSubsetOf<Class<T>> for T {
    #[inline(always)]
    fn is_subset_of(&self, class: &Class<T>) -> bool {
        class.contains(*self)
    }
}

impl<T: Atom> set::IsSubsetOf<Union<T>> for T
    where T: set::IsSubsetOf<T>
{
    #[inline]
    fn is_subset_of(&self, union: &Union<T>) -> bool {
        union.iter().any(|m| self.is_subset_of(m))
    }
}

impl<T: Atom> set::IsSubsetOf<Sequence<T>> for T
    where T: set::IsSubsetOf<T>
{
    #[inline]
    fn is_subset_of(&self, seq: &Sequence<T>) -> bool {
        seq.len() == 1 && self.is_subset_of(&seq[0])
    }
}

impl<T: Atom> set::IsSubsetOf<Repetition<T>> for T
    where T: set::IsSubsetOf<T>
{
    #[inline]
    fn is_subset_of(&self, rep: &Repetition<T>) -> bool {
        self.is_subset_of(rep.value()) && rep.count().contains(1)
    }
}

impl<T: Atom> set::IsSubsetOf<Element<T>> for T
    where T: set::IsSubsetOf<T> +
          set::IsSubsetOf<Repetition<Element<T>>> +
          set::IsSubsetOf<Sequence<Element<T>>> +
          set::IsSubsetOf<Union<Element<T>>> +
          set::IsSubsetOf<Anchor<T>>
{
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Wildcard => true,
            &Element::Atom(a) => *self == a,//self.is_subset_of(&a),

            #[cfg(feature = "pattern_class")]
            &Element::Class(ref class) => self.is_subset_of(class),
            &Element::Union(ref union) => self.is_subset_of(union),
            &Element::Repeat(ref rep) => self.is_subset_of(&**rep),
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),

            &Element::Sequence(ref seq) => self.is_subset_of(seq),
            &Element::Anchor(ref anch) => self.is_subset_of(anch),
            &Element::Not(ref element) => ! self.is_subset_of(&**element),
        }
    }
}

/// Trait for types whose values can be stepped through by increment/decrement
/// operatons
pub trait Step: PartialEq<Self> {
    ///  Fetch the next value after the one provided in the positive direction.
    ///  If the supplied value is already at its maximum, return it.
    fn increment(&self) -> Self;

    ///  Fetch the next value after the one provided in the negative direction.
    ///  If the supplied value is already at its minimum, return it.
    fn decrement(&self) -> Self;
}

/// Trait used to determine the distance between two atoms.
pub trait Distance {
    /// Calculate the distance between `self` and the given value, returning
    /// the number of `Self`-sized steps between them.
    fn distance(&self, b: &Self) -> usize;
}

macro_rules! impl_step_distance_for_primitives {
    ($first: tt, $($rest:tt),+) => (
        impl_step_distance_for_primitives!($first);
        impl_step_distance_for_primitives!($($rest),+);
    );
    ($tp: tt) => (
        impl Step for $tp {
            fn increment(&self) -> Self {
                if *self >= $tp::MAX { *self }
                else { ((*self) + 1) as $tp }
            }
            fn decrement(&self) -> Self {
                if *self == 0 { *self }
                else { (*self - 1) as $tp }
            }
        }
        impl Distance for $tp {
            fn distance(&self, b: &Self) -> usize {
                if *self > *b { (*self - *b) as usize }
                else { (*b - *self) as usize }
            }
        }
    );
}

impl_step_distance_for_primitives!(u8, u16, u32, u64, usize);

const SURROGATE_RANGE: Range<u32> = 0xD800..0xE000;

impl Distance for char {
    fn distance(&self, b: &Self) -> usize {
        let (a, b) = (cmp::min(*self, *b) as u32, cmp::max(*self, *b) as u32);
        let a_surrogate = SURROGATE_RANGE.contains(a);
        let b_surrogate = SURROGATE_RANGE.contains(b);

        if a_surrogate && b_surrogate { 0 }
        else if a_surrogate { b as usize }
        else if b_surrogate { a as usize }
        else if (a < SURROGATE_RANGE.start && b < SURROGATE_RANGE.start) || (a >= SURROGATE_RANGE.end && b >= SURROGATE_RANGE.end) {
            (b - a) as usize
        } else {
            (b - SURROGATE_RANGE.end + SURROGATE_RANGE.start - a) as usize
        }
    }
}

impl Step for char {
    fn increment(&self) -> Self {
        if *self >= char::MAX {
            *self
        } else {
            let mut o = *self as u32 + 1;
            if SURROGATE_RANGE.contains(o) {
                o += SURROGATE_RANGE.len() as u32;
            }

            // We've manually skipped the surrogate range and done range
            // checking above, so this *should* actually be safe.
            unsafe { char::from_u32_unchecked(o) }
        }
    }

    fn decrement(&self) -> Self {
        if *self == '\0' {
            *self
        } else {
            let mut o = *self as u32 - 1;
            if SURROGATE_RANGE.contains(o) {
                o -= SURROGATE_RANGE.len() as u32;
            }

            // We've manually skipped the surrogate range and done range
            // checking above, so this *should* actually be safe.
            unsafe { char::from_u32_unchecked(o) }
        }
    }
}

/// Atom type for use with mixed binary/text data.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub enum ByteOrChar {
    /// Single byte
    Byte(u8),
    /// Character
    Char(char)
}

impl From<u8> for ByteOrChar {
    fn from(byte: u8) -> Self {
        ByteOrChar::Byte(byte)
    }
}

impl From<char> for ByteOrChar {
    fn from(c: char) -> Self {
        ByteOrChar::Char(c)
    }
}

impl Distance for ByteOrChar {
    fn distance(&self, b: &Self) -> usize {
        Distance::distance(&Into::<char>::into(*self), &Into::<char>::into(*b))
    }
}

impl Step for ByteOrChar {
    fn increment(&self) -> Self {
        match self {
            &ByteOrChar::Byte(b) => ByteOrChar::Byte(b.increment()),
            &ByteOrChar::Char(c) => ByteOrChar::Char(c.increment()),
        }
    }
    fn decrement(&self) -> Self {
        match self {
            &ByteOrChar::Byte(b) => ByteOrChar::Byte(b.increment()),
            &ByteOrChar::Char(c) => ByteOrChar::Char(c.increment()),
        }
    }
}

impl Into<char> for ByteOrChar {
    fn into(self) -> char {
        match self {
            ByteOrChar::Byte(b) => b as char,
            ByteOrChar::Char(c) => c,
        }
    }
}

macro_rules! BoC_ascii_ext_forward {
    ($slf: ident, $name: ident) => (match $slf {
        &ByteOrChar::Byte(b) => b.$name(),
        &ByteOrChar::Char(c) => c.$name()
    });
    (mut $slf: ident, $name: ident) => (match *$slf {
        ByteOrChar::Byte(ref mut b) => b.$name(),
        ByteOrChar::Char(ref mut c) => c.$name()
    });
    ($slf: ident, $name: ident -> $conv: ident) => (match $slf {
        &ByteOrChar::Byte(b) => b.$name().$conv(),
        &ByteOrChar::Char(c) => c.$name().$conv()
    });
}

impl ascii::AsciiExt for ByteOrChar {
    type Owned = ByteOrChar;
    #[inline]
    fn is_ascii(&self) -> bool { BoC_ascii_ext_forward!(self, is_ascii) }
    #[inline]
    fn to_ascii_uppercase(&self) -> Self::Owned { BoC_ascii_ext_forward!(self, to_ascii_uppercase -> into) }
    #[inline]
    fn to_ascii_lowercase(&self) -> Self::Owned { BoC_ascii_ext_forward!(self, to_ascii_uppercase -> into) }
    #[inline]
    fn make_ascii_uppercase(&mut self) { BoC_ascii_ext_forward!(mut self, make_ascii_uppercase) }
    #[inline]
    fn make_ascii_lowercase(&mut self) { BoC_ascii_ext_forward!(mut self, make_ascii_lowercase) }

    #[inline]
    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        match self {
            &ByteOrChar::Byte(b1) => match other {
                &ByteOrChar::Byte(b2) => b1.eq_ignore_ascii_case(&b2),
                _ => false },
            &ByteOrChar::Char(c1) => match other {
                &ByteOrChar::Char(c2) => c1.eq_ignore_ascii_case(&c2),
                _ => false }
        }
    }
}
<commit_msg>pattern/atom: replace `IsSubsetOf` impls with single impl using `Contains`<commit_after>//! Atoms and atomic traits.

use std::{char, u8, u16, u32, u64, usize};
use std::{ascii, cmp};
use std::ops::Range;
use std::fmt::Debug;

use util::set;

apply_attrs! {
    cfg(not(feature = "pattern_class")) => {
        /// Trait-bounds requirements for atomic values in a pattern.
        pub trait Atom: Debug + Copy + Clone + Eq + Ord {}
        impl<T> Atom for T where T: Debug + Copy + Clone + Eq + Ord {}
    },
    cfg(feature = "pattern_class") => {
        use super::Class;

        /// Trait-bounds requirements for atomic values in a pattern.
        pub trait Atom: Debug + Copy + Clone + Eq + Ord + Distance + Step {}
        impl<T> Atom for T where T: Debug + Copy + Clone + Eq + Ord + Distance + Step {}
    }
}

impl<T: Atom, U> set::IsSubsetOf<U> for T
    where U: set::Contains<T>
{
    #[inline(always)]
    fn is_subset_of(&self, other: &U) -> bool {
        other.contains(*self)
    }
}

/// Trait for types whose values can be stepped through by increment/decrement
/// operatons
pub trait Step: PartialEq<Self> {
    ///  Fetch the next value after the one provided in the positive direction.
    ///  If the supplied value is already at its maximum, return it.
    fn increment(&self) -> Self;

    ///  Fetch the next value after the one provided in the negative direction.
    ///  If the supplied value is already at its minimum, return it.
    fn decrement(&self) -> Self;
}

/// Trait used to determine the distance between two atoms.
pub trait Distance {
    /// Calculate the distance between `self` and the given value, returning
    /// the number of `Self`-sized steps between them.
    fn distance(&self, b: &Self) -> usize;
}

macro_rules! impl_step_distance_for_primitives {
    ($first: tt, $($rest:tt),+) => (
        impl_step_distance_for_primitives!($first);
        impl_step_distance_for_primitives!($($rest),+);
    );
    ($tp: tt) => (
        impl Step for $tp {
            fn increment(&self) -> Self {
                if *self >= $tp::MAX { *self }
                else { ((*self) + 1) as $tp }
            }
            fn decrement(&self) -> Self {
                if *self == 0 { *self }
                else { (*self - 1) as $tp }
            }
        }
        impl Distance for $tp {
            fn distance(&self, b: &Self) -> usize {
                if *self > *b { (*self - *b) as usize }
                else { (*b - *self) as usize }
            }
        }
    );
}

impl_step_distance_for_primitives!(u8, u16, u32, u64, usize);

const SURROGATE_RANGE: Range<u32> = 0xD800..0xE000;

impl Distance for char {
    fn distance(&self, b: &Self) -> usize {
        let (a, b) = (cmp::min(*self, *b) as u32, cmp::max(*self, *b) as u32);
        let a_surrogate = SURROGATE_RANGE.contains(a);
        let b_surrogate = SURROGATE_RANGE.contains(b);

        if a_surrogate && b_surrogate { 0 }
        else if a_surrogate { b as usize }
        else if b_surrogate { a as usize }
        else if (a < SURROGATE_RANGE.start && b < SURROGATE_RANGE.start) || (a >= SURROGATE_RANGE.end && b >= SURROGATE_RANGE.end) {
            (b - a) as usize
        } else {
            (b - SURROGATE_RANGE.end + SURROGATE_RANGE.start - a) as usize
        }
    }
}

impl Step for char {
    fn increment(&self) -> Self {
        if *self >= char::MAX {
            *self
        } else {
            let mut o = *self as u32 + 1;
            if SURROGATE_RANGE.contains(o) {
                o += SURROGATE_RANGE.len() as u32;
            }

            // We've manually skipped the surrogate range and done range
            // checking above, so this *should* actually be safe.
            unsafe { char::from_u32_unchecked(o) }
        }
    }

    fn decrement(&self) -> Self {
        if *self == '\0' {
            *self
        } else {
            let mut o = *self as u32 - 1;
            if SURROGATE_RANGE.contains(o) {
                o -= SURROGATE_RANGE.len() as u32;
            }

            // We've manually skipped the surrogate range and done range
            // checking above, so this *should* actually be safe.
            unsafe { char::from_u32_unchecked(o) }
        }
    }
}

/// Atom type for use with mixed binary/text data.
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub enum ByteOrChar {
    /// Single byte
    Byte(u8),
    /// Character
    Char(char)
}

impl From<u8> for ByteOrChar {
    fn from(byte: u8) -> Self {
        ByteOrChar::Byte(byte)
    }
}

impl From<char> for ByteOrChar {
    fn from(c: char) -> Self {
        ByteOrChar::Char(c)
    }
}

impl Distance for ByteOrChar {
    fn distance(&self, b: &Self) -> usize {
        Distance::distance(&Into::<char>::into(*self), &Into::<char>::into(*b))
    }
}

impl Step for ByteOrChar {
    fn increment(&self) -> Self {
        match self {
            &ByteOrChar::Byte(b) => ByteOrChar::Byte(b.increment()),
            &ByteOrChar::Char(c) => ByteOrChar::Char(c.increment()),
        }
    }
    fn decrement(&self) -> Self {
        match self {
            &ByteOrChar::Byte(b) => ByteOrChar::Byte(b.increment()),
            &ByteOrChar::Char(c) => ByteOrChar::Char(c.increment()),
        }
    }
}

impl Into<char> for ByteOrChar {
    fn into(self) -> char {
        match self {
            ByteOrChar::Byte(b) => b as char,
            ByteOrChar::Char(c) => c,
        }
    }
}

macro_rules! BoC_ascii_ext_forward {
    ($slf: ident, $name: ident) => (match $slf {
        &ByteOrChar::Byte(b) => b.$name(),
        &ByteOrChar::Char(c) => c.$name()
    });
    (mut $slf: ident, $name: ident) => (match *$slf {
        ByteOrChar::Byte(ref mut b) => b.$name(),
        ByteOrChar::Char(ref mut c) => c.$name()
    });
    ($slf: ident, $name: ident -> $conv: ident) => (match $slf {
        &ByteOrChar::Byte(b) => b.$name().$conv(),
        &ByteOrChar::Char(c) => c.$name().$conv()
    });
}

impl ascii::AsciiExt for ByteOrChar {
    type Owned = ByteOrChar;
    #[inline]
    fn is_ascii(&self) -> bool { BoC_ascii_ext_forward!(self, is_ascii) }
    #[inline]
    fn to_ascii_uppercase(&self) -> Self::Owned { BoC_ascii_ext_forward!(self, to_ascii_uppercase -> into) }
    #[inline]
    fn to_ascii_lowercase(&self) -> Self::Owned { BoC_ascii_ext_forward!(self, to_ascii_uppercase -> into) }
    #[inline]
    fn make_ascii_uppercase(&mut self) { BoC_ascii_ext_forward!(mut self, make_ascii_uppercase) }
    #[inline]
    fn make_ascii_lowercase(&mut self) { BoC_ascii_ext_forward!(mut self, make_ascii_lowercase) }

    #[inline]
    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        match self {
            &ByteOrChar::Byte(b1) => match other {
                &ByteOrChar::Byte(b2) => b1.eq_ignore_ascii_case(&b2),
                _ => false },
            &ByteOrChar::Char(c1) => match other {
                &ByteOrChar::Char(c2) => c1.eq_ignore_ascii_case(&c2),
                _ => false }
        }
    }
}
<|endoftext|>


<commit_before>use solution::Solution;
use std::mpsc;

trait BestSolutionAdapter<S: Solution> {
    fn new_best(&self, item: S);
}

impl<S: Solution> BestSolutionAdapter<S> for mpsc::Sender<S> {
    fn new_best(&self, item: S) {
        self.send(item)
    }
}<commit_msg>Remove potential receiver, pending design<commit_after><|endoftext|>


<commit_before>//! The `optimizer` module contains iterators that allow a user to iterate over
//! `Program`s in order of increasing content
//!
//! The content is a measure of how complex a Program is.

use std::ops::{Rem, Div};
use super::TIS_100::{Program, Instruction, Source, Destination, Register};

/// Allows one to determine the content of certain constructs, e.g. `Program`s
/// or `Instruction`s
pub trait Content {
    /// the content of the construct
    fn content(&self) -> u32;
}

impl Content for Program {
    fn content(&self) -> u32 {
        let Program(ref instructions) = *self;

        instructions.iter().fold(0 as u32, |sum, instruction| sum + instruction.content())
    }
}

impl Content for Instruction {
    fn content(&self) -> u32 {
        match *self {
            Instruction::NOP => 1,
            Instruction::MOV(ref source, ref destination) => 1 + source.content() + destination.content(),
            Instruction::SWP => 1,
            Instruction::SAV => 1,
            Instruction::ADD(ref source) => 1 + source.content(),
            Instruction::SUB(ref source) => 1 + source.content(),
        }
    }
}

impl Content for Source {
    fn content(&self) -> u32 {
        match *self {
            Source::Literal(value) => 1 + (value.abs() as u32),
            _ => 1,
        }
    }
}

impl Content for Destination {
    fn content(&self) -> u32 {
        1
    }
}

/// Iterator over Programs
pub struct ProgramIterator {
    current: u32,
}

impl ProgramIterator {
    /// Create a `ProgramIterator`
    pub fn new() -> ProgramIterator {
        ProgramIterator { current: 0 }
    }
}

impl Iterator for ProgramIterator {
    type Item = Program;

    fn next(&mut self) -> Option<Program> {
        let instructions: Vec<Instruction> =
            digits_of(self.current, 33)
            .iter()
            .map(|digit| instruction_map(*digit))
            .collect();
        self.current += 1;
        Some(Program(instructions))
    }
}

fn digits_of(mut n: u32, base: u32) -> Vec<u32> {
    let mut digits: Vec<u32> = vec![];
    while n > 0 {
        digits.push(n.rem(base));
        n = n.div(base);
    }
    digits
}

fn instruction_map(index: u32) -> Instruction {
    match index % 33 {
        0 => Instruction::NOP,
        1 => Instruction::SWP,
        2 => Instruction::SAV,
        3 => Instruction::ADD(Source::Port),
        4 => Instruction::ADD(Source::Register(Register::NIL)),
        5 => Instruction::ADD(Source::Register(Register::ACC)),
        6 => Instruction::ADD(Source::Literal(0)),
        7 => Instruction::ADD(Source::Literal(1)),
        8 => Instruction::ADD(Source::Literal(-1)),
        9 => Instruction::SUB(Source::Port),
        10 => Instruction::SUB(Source::Register(Register::NIL)),
        11 => Instruction::SUB(Source::Register(Register::ACC)),
        12 => Instruction::SUB(Source::Literal(0)),
        13 => Instruction::SUB(Source::Literal(1)),
        14 => Instruction::SUB(Source::Literal(-1)),
        15 => Instruction::MOV(Source::Port, Destination::Port),
        16 => Instruction::MOV(Source::Register(Register::NIL), Destination::Port),
        17 => Instruction::MOV(Source::Register(Register::ACC), Destination::Port),
        18 => Instruction::MOV(Source::Literal(0), Destination::Port),
        19 => Instruction::MOV(Source::Literal(1), Destination::Port),
        20 => Instruction::MOV(Source::Literal(-1), Destination::Port),
        21 => Instruction::MOV(Source::Port, Destination::Register(Register::NIL)),
        22 => Instruction::MOV(Source::Register(Register::NIL), Destination::Register(Register::NIL)),
        23 => Instruction::MOV(Source::Register(Register::ACC), Destination::Register(Register::NIL)),
        24 => Instruction::MOV(Source::Literal(0), Destination::Register(Register::NIL)),
        25 => Instruction::MOV(Source::Literal(1), Destination::Register(Register::NIL)),
        26 => Instruction::MOV(Source::Literal(-1), Destination::Register(Register::NIL)),
        27 => Instruction::MOV(Source::Port, Destination::Register(Register::ACC)),
        28 => Instruction::MOV(Source::Register(Register::NIL), Destination::Register(Register::ACC)),
        29 => Instruction::MOV(Source::Register(Register::ACC), Destination::Register(Register::ACC)),
        30 => Instruction::MOV(Source::Literal(0), Destination::Register(Register::ACC)),
        31 => Instruction::MOV(Source::Literal(1), Destination::Register(Register::ACC)),
        32 => Instruction::MOV(Source::Literal(-1), Destination::Register(Register::ACC)),
        _ => Instruction::NOP,
    }
}

/// Iterator over Destination
pub struct DestinationIterator {
    current: i32,
    register_iterator: RegisterIterator,
}

impl DestinationIterator {
    /// create a DestinationIterator
    fn new() -> DestinationIterator {
        DestinationIterator {
            current: 0,
            register_iterator: RegisterIterator::new(),
        }
    }
}

impl Iterator for DestinationIterator {
    type Item = Destination;

    fn next(&mut self) -> Option<Destination> {
        let next_destination = match self.current {
            0 => Some(Destination::Port),
            _ => {
                self.register_iterator.next().map(|register| Destination::Register(register))
            }
        };
        self.current += 1;
        next_destination
    }
}

/// Iterator over Registers
pub struct RegisterIterator {
    current: u32,
}

impl RegisterIterator {
    fn new() -> RegisterIterator {
        RegisterIterator { current: 0 }
    }
}

impl Iterator for RegisterIterator {
    type Item = Register;

    fn next(&mut self) -> Option<Register> {
        let result = match self.current {
            0 => Some(Register::NIL),
            1 => Some(Register::ACC),
            _ => None
        };
        self.current += 1;
        result
    }
}

#[cfg(test)]
mod tests {
    use super::super::TIS_100::{Program,Instruction,Source,Destination,Register};
    use super::*;

    #[test]
    fn should_iterator_over_destinations() {
        let destinations: Vec<Destination> = DestinationIterator::new().collect();

        assert_eq!(Destination::Port, destinations[0]);
        assert_eq!(Destination::Register(Register::NIL), destinations[1]);
        assert_eq!(Destination::Register(Register::ACC), destinations[2]);
    }

    #[test]
    fn should_iterator_over_registers() {
        let registers: Vec<Register> = RegisterIterator::new().collect();

        assert_eq!(Register::NIL, registers[0]);
        assert_eq!(Register::ACC, registers[1]);
    }

    #[test]
    fn should_iterate_over_programs() {
        let programs: Vec<Program> = ProgramIterator::new().take(34).collect();

        assert_eq!(Program(vec![]), programs[0]);
        assert_eq!(Program(vec![Instruction::SWP]), programs[1]);
        assert_eq!(Program(vec![Instruction::SAV]), programs[2]);
        assert_eq!(Program(vec![
            Instruction::MOV(
                Source::Literal(-1),
                Destination::Register(Register::ACC)),
        ]), programs[32]);
        assert_eq!(Program(vec![
            Instruction::NOP,
            Instruction::SWP,
        ]), programs[33])
    }
}
<commit_msg>Remove unnecessary iterators<commit_after>//! The `optimizer` module contains iterators that allow a user to iterate over
//! `Program`s in order of increasing content
//!
//! The content is a measure of how complex a Program is.

use std::ops::{Rem, Div};
use super::TIS_100::{Program, Instruction, Source, Destination, Register};

/// Allows one to determine the content of certain constructs, e.g. `Program`s
/// or `Instruction`s
pub trait Content {
    /// the content of the construct
    fn content(&self) -> u32;
}

impl Content for Program {
    fn content(&self) -> u32 {
        let Program(ref instructions) = *self;

        instructions.iter().fold(0 as u32, |sum, instruction| sum + instruction.content())
    }
}

impl Content for Instruction {
    fn content(&self) -> u32 {
        match *self {
            Instruction::NOP => 1,
            Instruction::MOV(ref source, ref destination) => 1 + source.content() + destination.content(),
            Instruction::SWP => 1,
            Instruction::SAV => 1,
            Instruction::ADD(ref source) => 1 + source.content(),
            Instruction::SUB(ref source) => 1 + source.content(),
        }
    }
}

impl Content for Source {
    fn content(&self) -> u32 {
        match *self {
            Source::Literal(value) => 1 + (value.abs() as u32),
            _ => 1,
        }
    }
}

impl Content for Destination {
    fn content(&self) -> u32 {
        1
    }
}

/// Iterator over Programs
pub struct ProgramIterator {
    current: u32,
}

impl ProgramIterator {
    /// Create a `ProgramIterator`
    pub fn new() -> ProgramIterator {
        ProgramIterator { current: 0 }
    }
}

impl Iterator for ProgramIterator {
    type Item = Program;

    fn next(&mut self) -> Option<Program> {
        let instructions: Vec<Instruction> =
            digits_of(self.current, 33)
            .iter()
            .map(|digit| instruction_map(*digit))
            .collect();
        self.current += 1;
        Some(Program(instructions))
    }
}

fn digits_of(mut n: u32, base: u32) -> Vec<u32> {
    let mut digits: Vec<u32> = vec![];
    while n > 0 {
        digits.push(n.rem(base));
        n = n.div(base);
    }
    digits
}

fn instruction_map(index: u32) -> Instruction {
    match index % 33 {
        0 => Instruction::NOP,
        1 => Instruction::SWP,
        2 => Instruction::SAV,
        3 => Instruction::ADD(Source::Port),
        4 => Instruction::ADD(Source::Register(Register::NIL)),
        5 => Instruction::ADD(Source::Register(Register::ACC)),
        6 => Instruction::ADD(Source::Literal(0)),
        7 => Instruction::ADD(Source::Literal(1)),
        8 => Instruction::ADD(Source::Literal(-1)),
        9 => Instruction::SUB(Source::Port),
        10 => Instruction::SUB(Source::Register(Register::NIL)),
        11 => Instruction::SUB(Source::Register(Register::ACC)),
        12 => Instruction::SUB(Source::Literal(0)),
        13 => Instruction::SUB(Source::Literal(1)),
        14 => Instruction::SUB(Source::Literal(-1)),
        15 => Instruction::MOV(Source::Port, Destination::Port),
        16 => Instruction::MOV(Source::Register(Register::NIL), Destination::Port),
        17 => Instruction::MOV(Source::Register(Register::ACC), Destination::Port),
        18 => Instruction::MOV(Source::Literal(0), Destination::Port),
        19 => Instruction::MOV(Source::Literal(1), Destination::Port),
        20 => Instruction::MOV(Source::Literal(-1), Destination::Port),
        21 => Instruction::MOV(Source::Port, Destination::Register(Register::NIL)),
        22 => Instruction::MOV(Source::Register(Register::NIL), Destination::Register(Register::NIL)),
        23 => Instruction::MOV(Source::Register(Register::ACC), Destination::Register(Register::NIL)),
        24 => Instruction::MOV(Source::Literal(0), Destination::Register(Register::NIL)),
        25 => Instruction::MOV(Source::Literal(1), Destination::Register(Register::NIL)),
        26 => Instruction::MOV(Source::Literal(-1), Destination::Register(Register::NIL)),
        27 => Instruction::MOV(Source::Port, Destination::Register(Register::ACC)),
        28 => Instruction::MOV(Source::Register(Register::NIL), Destination::Register(Register::ACC)),
        29 => Instruction::MOV(Source::Register(Register::ACC), Destination::Register(Register::ACC)),
        30 => Instruction::MOV(Source::Literal(0), Destination::Register(Register::ACC)),
        31 => Instruction::MOV(Source::Literal(1), Destination::Register(Register::ACC)),
        32 => Instruction::MOV(Source::Literal(-1), Destination::Register(Register::ACC)),
        _ => Instruction::NOP,
    }
}

#[cfg(test)]
mod tests {
    use super::super::TIS_100::{Program,Instruction,Source,Destination,Register};
    use super::*;

    #[test]
    fn should_iterate_over_programs() {
        let programs: Vec<Program> = ProgramIterator::new().take(34).collect();

        assert_eq!(Program(vec![]), programs[0]);
        assert_eq!(Program(vec![Instruction::SWP]), programs[1]);
        assert_eq!(Program(vec![Instruction::SAV]), programs[2]);
        assert_eq!(Program(vec![
            Instruction::MOV(
                Source::Literal(-1),
                Destination::Register(Register::ACC)),
        ]), programs[32]);
        assert_eq!(Program(vec![
            Instruction::NOP,
            Instruction::SWP,
        ]), programs[33])
    }
}
<|endoftext|>


<commit_before>

use at::{AtRust, AtTrigger};
use plugins::get;

use select::document::Document;
use select::predicate::{Attr, Class, Name};
use rand;

pub fn get_eksi(query: &str) -> Option<Vec<String>> {

    let url = format!("https://eksisozluk.com/{}", query);

    let body = match get(&url[..]) {
        Some(n) => n,
        None => return None
    };

    let document = Document::from_str(&body[..]);

    let mut entries: Vec<String> = Vec::new();

    for entry in document.find(Attr("id", "entry-list")).find(Name("li")).iter() {
        let entry_text = entry.find(Class("content")).first().unwrap().text();
        // FIXME: Do I really need to clone text?
        entries.push(entry_text.clone());
    }

    return match entries.len() {
        0 => None,
        _ => Some(entries)
    };

}

pub fn eksi(trigger: &AtTrigger, at: &AtRust) {

    let entries = get_eksi(&trigger.command_message[..]);

    match entries {
        Some(entries) => at.reply(trigger, &entries[rand::random::<usize>() % entries.len()][..]),
        None => {}
    }

}
<commit_msg>Run rustfmt<commit_after>

use at::{AtRust, AtTrigger};
use plugins::get;

use select::document::Document;
use select::predicate::{Attr, Class, Name};
use rand;

pub fn get_eksi(query: &str) -> Option<Vec<String>> {

    let url = format!("https://eksisozluk.com/{}", query);

    let body = match get(&url[..]) {
        Some(n) => n,
        None => return None,
    };

    let document = Document::from_str(&body[..]);

    let mut entries: Vec<String> = Vec::new();

    for entry in document.find(Attr("id", "entry-list")).find(Name("li")).iter() {
        let entry_text = entry.find(Class("content")).first().unwrap().text();
        // FIXME: Do I really need to clone text?
        entries.push(entry_text.clone());
    }

    return match entries.len() {
        0 => None,
        _ => Some(entries),
    };

}

pub fn eksi(trigger: &AtTrigger, at: &AtRust) {

    let entries = get_eksi(&trigger.command_message[..]);

    match entries {
        Some(entries) => {
            at.reply(trigger,
                     &entries[rand::random::<usize>() % entries.len()][..])
        }
        None => {}
    }

}
<|endoftext|>


<commit_before>use libc;
use std;
use std::ptr::null;

use baseline;
use baseline::fct::BailoutInfo;
use baseline::map::CodeData;
use class::TypeParams;
use cpu;
use ctxt::{get_ctxt, FctId, SemContext, CTXT};
use exception::{handle_exception, stacktrace_from_es};
use execstate::ExecState;
use object::{Handle, Obj};
use os_cpu::*;
use safepoint;

#[cfg(target_family = "windows")]
use winapi::winnt::EXCEPTION_POINTERS;

#[cfg(target_family = "unix")]
pub fn register_signals(ctxt: &SemContext) {
    unsafe {
        let ptr = ctxt as *const SemContext as *const u8;
        CTXT = Some(ptr);

        let mut sa: libc::sigaction = std::mem::uninitialized();

        sa.sa_sigaction = handler as usize;
        libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
        sa.sa_flags = libc::SA_SIGINFO;

        if libc::sigaction(
            libc::SIGSEGV,
            &sa as *const libc::sigaction,
            0 as *mut libc::sigaction,
        ) == -1
        {
            libc::perror("sigaction for SIGSEGV failed".as_ptr() as *const libc::c_char);
        }

        if libc::sigaction(
            libc::SIGILL,
            &sa as *const libc::sigaction,
            0 as *mut libc::sigaction,
        ) == -1
        {
            libc::perror("sigaction for SIGILL failed".as_ptr() as *const libc::c_char);
        }
    }
}

#[cfg(target_family = "windows")]
pub fn register_signals(ctxt: &SemContext) {
    use kernel32::AddVectoredExceptionHandler;

    unsafe {
        AddVectoredExceptionHandler(1, Some(handler));
    }
}

#[cfg(target_family = "windows")]
extern "system" fn handler(exception: *mut EXCEPTION_POINTERS) -> i32 {
    use winapi::excpt;

    if fault_handler(exception) {
        return excpt::ExceptionContinueExecution.0 as i32;
    }

    excpt::ExceptionContinueSearch.0 as i32
}

#[cfg(target_family = "windows")]
fn fault_handler(exception: *mut EXCEPTION_POINTERS) -> bool {
    unsafe {
        let record = (*exception).ExceptionRecord;
        let context = (*exception).ContextRecord;
    }

    false
}

#[cfg(target_family = "unix")]
fn handler(signo: libc::c_int, info: *const siginfo_t, ucontext: *const u8) {
    let mut es = read_execstate(ucontext);
    let ctxt = get_ctxt();

    let addr = unsafe { (*info).si_addr } as *const u8;

    if let Some(trap) = detect_trap(signo as i32, &es) {
        match trap {
            Trap::COMPILER => compile_request(ctxt, &mut es, ucontext),

            Trap::DIV0 => {
                println!("division by 0");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(101);
                }
            }

            Trap::ASSERT => {
                println!("assert failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(101);
                }
            }

            Trap::INDEX_OUT_OF_BOUNDS => {
                println!("array index out of bounds");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(102);
                }
            }

            Trap::NIL => {
                println!("nil check failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(103);
                }
            }

            Trap::THROW => {
                let handler_found = handle_exception(&mut es);

                if handler_found {
                    write_execstate(&es, ucontext as *mut u8);
                } else {
                    println!("uncaught exception");
                    unsafe {
                        libc::_exit(104);
                    }
                }
            }

            Trap::CAST => {
                println!("cast failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(105);
                }
            }

            Trap::UNEXPECTED => {
                println!("unexpected exception");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(106);
                }
            }

            Trap::OOM => {
                println!("out of memory");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(107);
                }
            }
        }

    // is this is a failed nil check?
    } else if detect_nil_check(ctxt, es.pc) {
        println!("nil check failed");
        let stacktrace = stacktrace_from_es(ctxt, &es);
        stacktrace.dump(ctxt);
        unsafe {
            libc::_exit(103);
        }
    } else if detect_polling_page_check(ctxt, signo, addr) {
        // polling page read failed => enter safepoint
        safepoint::enter(&es);

    // otherwise trap not dected => crash
    } else {
        println!(
            "error: trap not detected (signal {}, addr {:?}).",
            signo, addr
        );
        println!();
        println!("{:?}", &es);
        println!();
        println!("polling page = {:?}", ctxt.polling_page.addr());
        println!();

        let code_map = ctxt.code_map.lock().unwrap();
        code_map.dump(ctxt);

        unsafe {
            libc::_exit(1);
        }
    }
}

fn detect_nil_check(ctxt: &SemContext, pc: usize) -> bool {
    let code_map = ctxt.code_map.lock().unwrap();

    if let Some(CodeData::Fct(fid)) = code_map.get(pc as *const u8) {
        let jit_fct = ctxt.jit_fcts[fid].borrow();
        let offset = pc - (jit_fct.fct_ptr() as usize);

        let jit_fct = jit_fct.to_base().expect("baseline expected");
        jit_fct.nil_check_for_offset(offset as i32)
    } else {
        false
    }
}

fn detect_polling_page_check(ctxt: &SemContext, signo: libc::c_int, addr: *const u8) -> bool {
    signo == libc::SIGSEGV && ctxt.polling_page.addr() == addr
}

fn compile_request(ctxt: &SemContext, es: &mut ExecState, ucontext: *const u8) {
    // get return address from top of stack
    let ra = cpu::ra_from_execstate(es);

    let bailout = {
        let data = {
            let code_map = ctxt.code_map.lock().unwrap();
            code_map
                .get(ra as *const u8)
                .expect("return address not found")
        };

        let fct_id = match data {
            CodeData::Fct(fct_id) => fct_id,
            _ => panic!("expected function for code"),
        };

        let jit_fct = ctxt.jit_fcts[fct_id].borrow();

        let offset = ra - jit_fct.fct_ptr() as usize;
        let jit_fct = jit_fct.to_base().expect("baseline expected");
        jit_fct
            .bailouts
            .get(offset as i32)
            .expect("bailout info not found")
            .clone()
    };

    let mut dtn = cpu::dtn_from_execution_state(es);

    ctxt.use_dtn(&mut dtn, || match bailout {
        BailoutInfo::Compile(fct_id, disp, ref cls_tps, ref fct_tps) => {
            patch_fct_call(ctxt, es, ra, fct_id, cls_tps, fct_tps, disp)
        }
        BailoutInfo::VirtCompile(vtable_index, ref fct_tps) => {
            patch_vtable_call(ctxt, es, vtable_index, fct_tps)
        }
    });

    write_execstate(es, ucontext as *mut u8);
}

fn patch_vtable_call(
    ctxt: &SemContext,
    es: &mut ExecState,
    vtable_index: u32,
    fct_tps: &TypeParams,
) {
    let obj: Handle<Obj> = cpu::receiver_from_execstate(es).into();

    let vtable = obj.header().vtbl();
    let cls_id = vtable.class().cls_id;
    let cls = ctxt.classes[cls_id].borrow();

    let mut fct_ptr = null();

    for &fct_id in &cls.methods {
        let fct = ctxt.fcts[fct_id].borrow();

        if Some(vtable_index) == fct.vtable_index {
            let empty = TypeParams::empty();
            fct_ptr = baseline::generate(ctxt, fct_id, &empty, fct_tps);
            break;
        }
    }

    let methodtable = vtable.table_mut();
    methodtable[vtable_index as usize] = fct_ptr as usize;

    // execute fct call again
    es.pc = fct_ptr as usize;
}

pub fn patch_fct_call(
    ctxt: &SemContext,
    es: &mut ExecState,
    ra: usize,
    fct_id: FctId,
    cls_tps: &TypeParams,
    fct_tps: &TypeParams,
    disp: i32,
) {
    let fct_ptr = baseline::generate(ctxt, fct_id, cls_tps, fct_tps);
    let fct_addr: *mut usize = (ra as isize - disp as isize) as *mut _;

    // write function pointer
    unsafe {
        *fct_addr = fct_ptr as usize;
    }

    // execute fct call again
    es.pc = fct_ptr as usize;
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Trap {
    COMPILER,
    DIV0,
    ASSERT,
    INDEX_OUT_OF_BOUNDS,
    NIL,
    THROW,
    CAST,
    UNEXPECTED,
    OOM,
}

impl Trap {
    pub fn int(self) -> u32 {
        match self {
            Trap::COMPILER => 0,
            Trap::DIV0 => 1,
            Trap::ASSERT => 2,
            Trap::INDEX_OUT_OF_BOUNDS => 3,
            Trap::NIL => 4,
            Trap::THROW => 5,
            Trap::CAST => 6,
            Trap::UNEXPECTED => 7,
            Trap::OOM => 8,
        }
    }

    pub fn from(value: u32) -> Option<Trap> {
        match value {
            0 => Some(Trap::COMPILER),
            1 => Some(Trap::DIV0),
            2 => Some(Trap::ASSERT),
            3 => Some(Trap::INDEX_OUT_OF_BOUNDS),
            4 => Some(Trap::NIL),
            5 => Some(Trap::THROW),
            6 => Some(Trap::CAST),
            7 => Some(Trap::UNEXPECTED),
            8 => Some(Trap::OOM),
            _ => None,
        }
    }
}

struct siginfo_t {
    pub si_signo: libc::c_int,
    pub si_errno: libc::c_int,
    pub si_code: libc::c_int,
    pub si_addr: *const libc::c_void,
}
<commit_msg>remove old compiler signal handling<commit_after>use libc;
use std;

use baseline::map::CodeData;
use ctxt::{get_ctxt, SemContext, CTXT};
use exception::{handle_exception, stacktrace_from_es};
use os_cpu::*;
use safepoint;

#[cfg(target_family = "windows")]
use winapi::winnt::EXCEPTION_POINTERS;

#[cfg(target_family = "unix")]
pub fn register_signals(ctxt: &SemContext) {
    unsafe {
        let ptr = ctxt as *const SemContext as *const u8;
        CTXT = Some(ptr);

        let mut sa: libc::sigaction = std::mem::uninitialized();

        sa.sa_sigaction = handler as usize;
        libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
        sa.sa_flags = libc::SA_SIGINFO;

        if libc::sigaction(
            libc::SIGSEGV,
            &sa as *const libc::sigaction,
            0 as *mut libc::sigaction,
        ) == -1
        {
            libc::perror("sigaction for SIGSEGV failed".as_ptr() as *const libc::c_char);
        }

        if libc::sigaction(
            libc::SIGILL,
            &sa as *const libc::sigaction,
            0 as *mut libc::sigaction,
        ) == -1
        {
            libc::perror("sigaction for SIGILL failed".as_ptr() as *const libc::c_char);
        }
    }
}

#[cfg(target_family = "windows")]
pub fn register_signals(ctxt: &SemContext) {
    use kernel32::AddVectoredExceptionHandler;

    unsafe {
        AddVectoredExceptionHandler(1, Some(handler));
    }
}

#[cfg(target_family = "windows")]
extern "system" fn handler(exception: *mut EXCEPTION_POINTERS) -> i32 {
    use winapi::excpt;

    if fault_handler(exception) {
        return excpt::ExceptionContinueExecution.0 as i32;
    }

    excpt::ExceptionContinueSearch.0 as i32
}

#[cfg(target_family = "windows")]
fn fault_handler(exception: *mut EXCEPTION_POINTERS) -> bool {
    unsafe {
        let record = (*exception).ExceptionRecord;
        let context = (*exception).ContextRecord;
    }

    false
}

#[cfg(target_family = "unix")]
fn handler(signo: libc::c_int, info: *const siginfo_t, ucontext: *const u8) {
    let mut es = read_execstate(ucontext);
    let ctxt = get_ctxt();

    let addr = unsafe { (*info).si_addr } as *const u8;

    if let Some(trap) = detect_trap(signo as i32, &es) {
        match trap {
            Trap::DIV0 => {
                println!("division by 0");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(101);
                }
            }

            Trap::ASSERT => {
                println!("assert failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(101);
                }
            }

            Trap::INDEX_OUT_OF_BOUNDS => {
                println!("array index out of bounds");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(102);
                }
            }

            Trap::NIL => {
                println!("nil check failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(103);
                }
            }

            Trap::THROW => {
                let handler_found = handle_exception(&mut es);

                if handler_found {
                    write_execstate(&es, ucontext as *mut u8);
                } else {
                    println!("uncaught exception");
                    unsafe {
                        libc::_exit(104);
                    }
                }
            }

            Trap::CAST => {
                println!("cast failed");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(105);
                }
            }

            Trap::UNEXPECTED => {
                println!("unexpected exception");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(106);
                }
            }

            Trap::OOM => {
                println!("out of memory");
                let stacktrace = stacktrace_from_es(ctxt, &es);
                stacktrace.dump(ctxt);
                unsafe {
                    libc::_exit(107);
                }
            }
        }

    // is this is a failed nil check?
    } else if detect_nil_check(ctxt, es.pc) {
        println!("nil check failed");
        let stacktrace = stacktrace_from_es(ctxt, &es);
        stacktrace.dump(ctxt);
        unsafe {
            libc::_exit(103);
        }
    } else if detect_polling_page_check(ctxt, signo, addr) {
        // polling page read failed => enter safepoint
        safepoint::enter(&es);

    // otherwise trap not dected => crash
    } else {
        println!(
            "error: trap not detected (signal {}, addr {:?}).",
            signo, addr
        );
        println!();
        println!("{:?}", &es);
        println!();
        println!("polling page = {:?}", ctxt.polling_page.addr());
        println!();

        let code_map = ctxt.code_map.lock().unwrap();
        code_map.dump(ctxt);

        unsafe {
            libc::_exit(1);
        }
    }
}

fn detect_nil_check(ctxt: &SemContext, pc: usize) -> bool {
    let code_map = ctxt.code_map.lock().unwrap();

    if let Some(CodeData::Fct(fid)) = code_map.get(pc as *const u8) {
        let jit_fct = ctxt.jit_fcts[fid].borrow();
        let offset = pc - (jit_fct.fct_ptr() as usize);

        let jit_fct = jit_fct.to_base().expect("baseline expected");
        jit_fct.nil_check_for_offset(offset as i32)
    } else {
        false
    }
}

fn detect_polling_page_check(ctxt: &SemContext, signo: libc::c_int, addr: *const u8) -> bool {
    signo == libc::SIGSEGV && ctxt.polling_page.addr() == addr
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Trap {
    DIV0,
    ASSERT,
    INDEX_OUT_OF_BOUNDS,
    NIL,
    THROW,
    CAST,
    UNEXPECTED,
    OOM,
}

impl Trap {
    pub fn int(self) -> u32 {
        match self {
            Trap::DIV0 => 1,
            Trap::ASSERT => 2,
            Trap::INDEX_OUT_OF_BOUNDS => 3,
            Trap::NIL => 4,
            Trap::THROW => 5,
            Trap::CAST => 6,
            Trap::UNEXPECTED => 7,
            Trap::OOM => 8,
        }
    }

    pub fn from(value: u32) -> Option<Trap> {
        match value {
            1 => Some(Trap::DIV0),
            2 => Some(Trap::ASSERT),
            3 => Some(Trap::INDEX_OUT_OF_BOUNDS),
            4 => Some(Trap::NIL),
            5 => Some(Trap::THROW),
            6 => Some(Trap::CAST),
            7 => Some(Trap::UNEXPECTED),
            8 => Some(Trap::OOM),
            _ => None,
        }
    }
}

struct siginfo_t {
    pub si_signo: libc::c_int,
    pub si_errno: libc::c_int,
    pub si_code: libc::c_int,
    pub si_addr: *const libc::c_void,
}
<|endoftext|>


<commit_before>//! Patch of a VM, indicating different hard-fork of the Ethereum
//! block range.

mod precompiled;

pub use self::precompiled::*;

use bigint::{Address, Gas, U256, H160};

/// Account patch for account related variables.
pub trait AccountPatch {
    /// Initial nonce for accounts.
    fn initial_nonce() -> U256;
    /// Initial create nonce for accounts. (EIP161.a)
    fn initial_create_nonce() -> U256;
    /// Whether empty accounts are considered to be existing. (EIP161.b/EIP161.c/EIP161.d)
    fn empty_considered_exists() -> bool;
    /// Whether to allow partial change IncreaseBalance.
    fn allow_partial_change() -> bool {
        Self::empty_considered_exists()
    }
}

/// Mainnet account patch
pub struct EmbeddedAccountPatch;
impl AccountPatch for EmbeddedAccountPatch {
    fn initial_nonce() -> U256 { U256::zero() }
    fn initial_create_nonce() -> U256 { Self::initial_nonce() }
    fn empty_considered_exists() -> bool { true }
}

/// Mainnet account patch
pub struct EmbeddedByzantiumAccountPatch;
impl AccountPatch for EmbeddedByzantiumAccountPatch {
    fn initial_nonce() -> U256 { U256::zero() }
    fn initial_create_nonce() -> U256 { Self::initial_nonce() + U256::one() }
    fn empty_considered_exists() -> bool { false }
}

/// Represents different block range context.
pub trait Patch {
    /// Account patch
    type Account: AccountPatch;

    /// Maximum contract size.
    fn code_deposit_limit() -> Option<usize>;
    /// Limit of the call stack.
    fn callstack_limit() -> usize;
    /// Gas paid for extcode.
    fn gas_extcode() -> Gas;
    /// Gas paid for BALANCE opcode.
    fn gas_balance() -> Gas;
    /// Gas paid for SLOAD opcode.
    fn gas_sload() -> Gas;
    /// Gas paid for SUICIDE opcode.
    fn gas_suicide() -> Gas;
    /// Gas paid for SUICIDE opcode when it hits a new account.
    fn gas_suicide_new_account() -> Gas;
    /// Gas paid for CALL opcode.
    fn gas_call() -> Gas;
    /// Gas paid for EXP opcode for every byte.
    fn gas_expbyte() -> Gas;
    /// Gas paid for a contract creation transaction.
    fn gas_transaction_create() -> Gas;
    /// Whether to force code deposit even if it does not have enough
    /// gas.
    fn force_code_deposit() -> bool;
    /// Whether the EVM has DELEGATECALL opcode.
    fn has_delegate_call() -> bool;
    /// Whether the EVM has STATICCALL opcode.
    fn has_static_call() -> bool;
    /// Whether the EVM has REVERT opcode.
    fn has_revert() -> bool;
    /// Whether the EVM has RETURNDATASIZE and RETURNDATACOPY opcode.
    fn has_return_data() -> bool;
    /// Whether the EVM has SHL, SHR and SAR
    fn has_bitwise_shift() -> bool;
    /// Whether to throw out of gas error when
    /// CALL/CALLCODE/DELEGATECALL requires more than maximum amount
    /// of gas.
    fn err_on_call_with_more_gas() -> bool;
    /// If true, only consume at maximum l64(after_gas) when
    /// CALL/CALLCODE/DELEGATECALL.
    fn call_create_l64_after_gas() -> bool;
    /// Maximum size of the memory, in bytes.
    fn memory_limit() -> usize;
    /// Precompiled contracts at given address, with required code,
    /// and its definition.
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)];
}

/// Default precompiled collections.
pub static EMBEDDED_PRECOMPILEDS: [(Address, Option<&'static [u8]>, &'static Precompiled); 4] = [
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x01]),
     None,
     &ECREC_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x02]),
     None,
     &SHA256_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x03]),
     None,
     &RIP160_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x04]),
     None,
     &ID_PRECOMPILED),
];

/// Patch sepcific for the `jsontests` crate.
pub struct VMTestPatch;
impl Patch for VMTestPatch {
    type Account = EmbeddedAccountPatch;

    fn code_deposit_limit() -> Option<usize> { None }
    fn callstack_limit() -> usize { 2 }
    fn gas_extcode() -> Gas { Gas::from(20usize) }
    fn gas_balance() -> Gas { Gas::from(20usize) }
    fn gas_sload() -> Gas { Gas::from(50usize) }
    fn gas_suicide() -> Gas { Gas::from(0usize) }
    fn gas_suicide_new_account() -> Gas { Gas::from(0usize) }
    fn gas_call() -> Gas { Gas::from(40usize) }
    fn gas_expbyte() -> Gas { Gas::from(10usize) }
    fn gas_transaction_create() -> Gas { Gas::from(0usize) }
    fn force_code_deposit() -> bool { true }
    fn has_delegate_call() -> bool { false }
    fn has_static_call() -> bool { false }
    fn has_revert() -> bool { false }
    fn has_return_data() -> bool { false }
    fn has_bitwise_shift() -> bool { true }
    fn err_on_call_with_more_gas() -> bool { true }
    fn call_create_l64_after_gas() -> bool { false }
    fn memory_limit() -> usize { usize::max_value() }
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
        &EMBEDDED_PRECOMPILEDS }
}

/// Embedded patch.
pub struct EmbeddedPatch;
impl Patch for EmbeddedPatch {
    type Account = EmbeddedAccountPatch;

    fn code_deposit_limit() -> Option<usize> { None }
    fn callstack_limit() -> usize { 1024 }
    fn gas_extcode() -> Gas { Gas::from(700usize) }
    fn gas_balance() -> Gas { Gas::from(400usize) }
    fn gas_sload() -> Gas { Gas::from(200usize) }
    fn gas_suicide() -> Gas { Gas::from(5000usize) }
    fn gas_suicide_new_account() -> Gas { Gas::from(25000usize) }
    fn gas_call() -> Gas { Gas::from(700usize) }
    fn gas_expbyte() -> Gas { Gas::from(50usize) }
    fn gas_transaction_create() -> Gas { Gas::from(32000usize) }
    fn force_code_deposit() -> bool { false }
    fn has_delegate_call() -> bool { true }
    fn has_static_call() -> bool { false }
    fn has_revert() -> bool { false }
    fn has_return_data() -> bool { false }
    fn has_bitwise_shift() -> bool { false }
    fn err_on_call_with_more_gas() -> bool { false }
    fn call_create_l64_after_gas() -> bool { true }
    fn memory_limit() -> usize { usize::max_value() }
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
        &EMBEDDED_PRECOMPILEDS }
}

/// Constantinople patch (includes Byzantium changes)
pub struct EmbeddedConstantinoplePatch<A: AccountPatch>(PhantomData<A>);
impl<A: AccountPatch> Patch for EmbeddedConstantinoplePatch<A> {
    type Account = A;

    fn code_deposit_limit() -> Option<usize> { None }
    fn callstack_limit() -> usize { 1024 }
    fn gas_extcode() -> Gas { Gas::from(700usize) }
    fn gas_balance() -> Gas { Gas::from(400usize) }
    fn gas_sload() -> Gas { Gas::from(200usize) }
    fn gas_suicide() -> Gas { Gas::from(5000usize) }
    fn gas_suicide_new_account() -> Gas { Gas::from(25000usize) }
    fn gas_call() -> Gas { Gas::from(700usize) }
    fn gas_expbyte() -> Gas { Gas::from(50usize) }
    fn gas_transaction_create() -> Gas { Gas::from(32000usize) }
    fn force_code_deposit() -> bool { false }
    fn has_delegate_call() -> bool { true }
    fn has_static_call() -> bool { true }
    fn has_revert() -> bool { true }
    fn has_return_data() -> bool { true }
    fn has_bitwise_shift() -> bool { true }
    fn err_on_call_with_more_gas() -> bool { true }
    fn call_create_l64_after_gas() -> bool { false }
    fn memory_limit() -> usize { usize::max_value() }
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
        &EMBEDDED_PRECOMPILEDS }
}

<commit_msg>revert adding the embedded constantinople patch<commit_after>//! Patch of a VM, indicating different hard-fork of the Ethereum
//! block range.

mod precompiled;

pub use self::precompiled::*;

use bigint::{Address, Gas, U256, H160};

/// Account patch for account related variables.
pub trait AccountPatch {
    /// Initial nonce for accounts.
    fn initial_nonce() -> U256;
    /// Initial create nonce for accounts. (EIP161.a)
    fn initial_create_nonce() -> U256;
    /// Whether empty accounts are considered to be existing. (EIP161.b/EIP161.c/EIP161.d)
    fn empty_considered_exists() -> bool;
    /// Whether to allow partial change IncreaseBalance.
    fn allow_partial_change() -> bool {
        Self::empty_considered_exists()
    }
}

/// Mainnet account patch
pub struct EmbeddedAccountPatch;
impl AccountPatch for EmbeddedAccountPatch {
    fn initial_nonce() -> U256 { U256::zero() }
    fn initial_create_nonce() -> U256 { Self::initial_nonce() }
    fn empty_considered_exists() -> bool { true }
}

/// Mainnet account patch
pub struct EmbeddedByzantiumAccountPatch;
impl AccountPatch for EmbeddedByzantiumAccountPatch {
    fn initial_nonce() -> U256 { U256::zero() }
    fn initial_create_nonce() -> U256 { Self::initial_nonce() + U256::one() }
    fn empty_considered_exists() -> bool { false }
}

/// Represents different block range context.
pub trait Patch {
    /// Account patch
    type Account: AccountPatch;

    /// Maximum contract size.
    fn code_deposit_limit() -> Option<usize>;
    /// Limit of the call stack.
    fn callstack_limit() -> usize;
    /// Gas paid for extcode.
    fn gas_extcode() -> Gas;
    /// Gas paid for BALANCE opcode.
    fn gas_balance() -> Gas;
    /// Gas paid for SLOAD opcode.
    fn gas_sload() -> Gas;
    /// Gas paid for SUICIDE opcode.
    fn gas_suicide() -> Gas;
    /// Gas paid for SUICIDE opcode when it hits a new account.
    fn gas_suicide_new_account() -> Gas;
    /// Gas paid for CALL opcode.
    fn gas_call() -> Gas;
    /// Gas paid for EXP opcode for every byte.
    fn gas_expbyte() -> Gas;
    /// Gas paid for a contract creation transaction.
    fn gas_transaction_create() -> Gas;
    /// Whether to force code deposit even if it does not have enough
    /// gas.
    fn force_code_deposit() -> bool;
    /// Whether the EVM has DELEGATECALL opcode.
    fn has_delegate_call() -> bool;
    /// Whether the EVM has STATICCALL opcode.
    fn has_static_call() -> bool;
    /// Whether the EVM has REVERT opcode.
    fn has_revert() -> bool;
    /// Whether the EVM has RETURNDATASIZE and RETURNDATACOPY opcode.
    fn has_return_data() -> bool;
    /// Whether the EVM has SHL, SHR and SAR
    fn has_bitwise_shift() -> bool;
    /// Whether to throw out of gas error when
    /// CALL/CALLCODE/DELEGATECALL requires more than maximum amount
    /// of gas.
    fn err_on_call_with_more_gas() -> bool;
    /// If true, only consume at maximum l64(after_gas) when
    /// CALL/CALLCODE/DELEGATECALL.
    fn call_create_l64_after_gas() -> bool;
    /// Maximum size of the memory, in bytes.
    fn memory_limit() -> usize;
    /// Precompiled contracts at given address, with required code,
    /// and its definition.
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)];
}

/// Default precompiled collections.
pub static EMBEDDED_PRECOMPILEDS: [(Address, Option<&'static [u8]>, &'static Precompiled); 4] = [
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x01]),
     None,
     &ECREC_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x02]),
     None,
     &SHA256_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x03]),
     None,
     &RIP160_PRECOMPILED),
    (H160([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x04]),
     None,
     &ID_PRECOMPILED),
];

/// Patch sepcific for the `jsontests` crate.
pub struct VMTestPatch;
impl Patch for VMTestPatch {
    type Account = EmbeddedAccountPatch;

    fn code_deposit_limit() -> Option<usize> { None }
    fn callstack_limit() -> usize { 2 }
    fn gas_extcode() -> Gas { Gas::from(20usize) }
    fn gas_balance() -> Gas { Gas::from(20usize) }
    fn gas_sload() -> Gas { Gas::from(50usize) }
    fn gas_suicide() -> Gas { Gas::from(0usize) }
    fn gas_suicide_new_account() -> Gas { Gas::from(0usize) }
    fn gas_call() -> Gas { Gas::from(40usize) }
    fn gas_expbyte() -> Gas { Gas::from(10usize) }
    fn gas_transaction_create() -> Gas { Gas::from(0usize) }
    fn force_code_deposit() -> bool { true }
    fn has_delegate_call() -> bool { false }
    fn has_static_call() -> bool { false }
    fn has_revert() -> bool { false }
    fn has_return_data() -> bool { false }
    fn has_bitwise_shift() -> bool { true }
    fn err_on_call_with_more_gas() -> bool { true }
    fn call_create_l64_after_gas() -> bool { false }
    fn memory_limit() -> usize { usize::max_value() }
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
        &EMBEDDED_PRECOMPILEDS }
}

/// Embedded patch.
pub struct EmbeddedPatch;
impl Patch for EmbeddedPatch {
    type Account = EmbeddedAccountPatch;

    fn code_deposit_limit() -> Option<usize> { None }
    fn callstack_limit() -> usize { 1024 }
    fn gas_extcode() -> Gas { Gas::from(700usize) }
    fn gas_balance() -> Gas { Gas::from(400usize) }
    fn gas_sload() -> Gas { Gas::from(200usize) }
    fn gas_suicide() -> Gas { Gas::from(5000usize) }
    fn gas_suicide_new_account() -> Gas { Gas::from(25000usize) }
    fn gas_call() -> Gas { Gas::from(700usize) }
    fn gas_expbyte() -> Gas { Gas::from(50usize) }
    fn gas_transaction_create() -> Gas { Gas::from(32000usize) }
    fn force_code_deposit() -> bool { false }
    fn has_delegate_call() -> bool { true }
    fn has_static_call() -> bool { false }
    fn has_revert() -> bool { false }
    fn has_return_data() -> bool { false }
    fn has_bitwise_shift() -> bool { false }
    fn err_on_call_with_more_gas() -> bool { false }
    fn call_create_l64_after_gas() -> bool { true }
    fn memory_limit() -> usize { usize::max_value() }
    fn precompileds() -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
        &EMBEDDED_PRECOMPILEDS
    }
}

<|endoftext|>