<commit_before>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:path) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instad of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name = uninit.as_ptr();
    };
}
#[cfg(not(maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:path) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB when the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Deref-coercion protection macro.
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[cfg_attr(allow_clippy, allow(clippy::unneeded_field_pattern))]
        let $type { $field: _, .. };
    };
}

/// Calculates the offset of the specified field from the start of the struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[cfg(not(feature = "unstable_const"))]
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get the field address. This is UB because we are creating a reference to
        // the uninitialized field.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the `field_check!` we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        let field_ptr = unsafe { &(*base_ptr).$field as *const _ };
        let offset = (field_ptr as usize) - (base_ptr as usize);
        offset
    }};
}

#[cfg(feature = "unstable_const")]
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        // No UB here, and the pointer does not dangle, either.
        let uninit = $crate::mem::MaybeUninit::<$parent>::uninit();
        unsafe {
            // This, on the other hand, *is* UB, since we're creating a reference
            // to uninitialized data.
            // Unfortunately it's the best we can do at the moment.
            let base_ref = $crate::mem::transmute::<_, &$parent>(&uninit);
            let base_u8_ptr = base_ref as *const _ as *const u8;

            // This is another reference to uninitialized data.
            // Crucially, we know that this will not trigger a deref coercion because
            // of the `field_check!` we did above.
            let field_u8_ptr = &base_ref.$field as *const _ as *const u8;
            let offset = field_u8_ptr.offset_from(base_u8_ptr) as usize;
            offset
        }
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg_attr(miri, ignore)] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }

    #[test]
    fn path() {
        mod sub {
            #[repr(C)]
            pub struct Foo {
                pub x: u32,
            }
        }

        assert_eq!(offset_of!(sub::Foo, x), 0);
    }

    #[test]
    fn inside_generic_method() {
        struct Pair<T, U>(T, U);

        fn foo<T, U>(_: Pair<T, U>) -> usize {
            offset_of!(Pair<T, U>, 1)
        }

        assert_eq!(foo(Pair(0, 0)), 4);
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_offset() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!([0; offset_of!(Foo, b)].len(), 4);
    }
}
<commit_msg>Fix a typo in comment<commit_after>// Copyright (c) 2017 Gilad Naaman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

/// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as
/// much as is possible currently.
#[cfg(maybe_uninit)]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:path) => {
        // No UB here, and the pointer does not dangle, either.
        // But we have to make sure that `uninit` lives long enough,
        // so it has to be in the same scope as `$name`. That's why
        // `let_base_ptr` declares a variable (several, actually)
        // instead of returning one.
        let uninit = $crate::mem::MaybeUninit::<$type>::uninit();
        let $name = uninit.as_ptr();
    };
}
#[cfg(not(maybe_uninit))]
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__let_base_ptr {
    ($name:ident, $type:path) => {
        // No UB right here, but we will later dereference this pointer to
        // offset into a field, and that is UB when the pointer is dangling.
        let $name = $crate::mem::align_of::<$type>() as *const $type;
    };
}

/// Deref-coercion protection macro.
#[macro_export]
#[doc(hidden)]
macro_rules! _memoffset__field_check {
    ($type:path, $field:tt) => {
        // Make sure the field actually exists. This line ensures that a
        // compile-time error is generated if $field is accessed through a
        // Deref impl.
        #[cfg_attr(allow_clippy, allow(clippy::unneeded_field_pattern))]
        let $type { $field: _, .. };
    };
}

/// Calculates the offset of the specified field from the start of the struct.
///
/// ## Examples
/// ```
/// #[macro_use]
/// extern crate memoffset;
///
/// #[repr(C, packed)]
/// struct Foo {
///     a: u32,
///     b: u64,
///     c: [u8; 5]
/// }
///
/// fn main() {
///     assert_eq!(offset_of!(Foo, a), 0);
///     assert_eq!(offset_of!(Foo, b), 4);
/// }
/// ```
#[cfg(not(feature = "unstable_const"))]
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        _memoffset__let_base_ptr!(base_ptr, $parent);
        // Get the field address. This is UB because we are creating a reference to
        // the uninitialized field.
        // Crucially, we know that this will not trigger a deref coercion because
        // of the `field_check!` we did above.
        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
        let field_ptr = unsafe { &(*base_ptr).$field as *const _ };
        let offset = (field_ptr as usize) - (base_ptr as usize);
        offset
    }};
}

#[cfg(feature = "unstable_const")]
#[macro_export(local_inner_macros)]
macro_rules! offset_of {
    ($parent:path, $field:tt) => {{
        _memoffset__field_check!($parent, $field);

        // Get a base pointer.
        // No UB here, and the pointer does not dangle, either.
        let uninit = $crate::mem::MaybeUninit::<$parent>::uninit();
        unsafe {
            // This, on the other hand, *is* UB, since we're creating a reference
            // to uninitialized data.
            // Unfortunately it's the best we can do at the moment.
            let base_ref = $crate::mem::transmute::<_, &$parent>(&uninit);
            let base_u8_ptr = base_ref as *const _ as *const u8;

            // This is another reference to uninitialized data.
            // Crucially, we know that this will not trigger a deref coercion because
            // of the `field_check!` we did above.
            let field_u8_ptr = &base_ref.$field as *const _ as *const u8;
            let offset = field_u8_ptr.offset_from(base_u8_ptr) as usize;
            offset
        }
    }};
}

#[cfg(test)]
mod tests {
    #[test]
    fn offset_simple() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 8);
    }

    #[test]
    #[cfg_attr(miri, ignore)] // this creates unaligned references
    fn offset_simple_packed() {
        #[repr(C, packed)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!(offset_of!(Foo, a), 0);
        assert_eq!(offset_of!(Foo, b), 4);
        assert_eq!(offset_of!(Foo, c), 6);
    }

    #[test]
    fn tuple_struct() {
        #[repr(C)]
        struct Tup(i32, i32);

        assert_eq!(offset_of!(Tup, 0), 0);
        assert_eq!(offset_of!(Tup, 1), 4);
    }

    #[test]
    fn path() {
        mod sub {
            #[repr(C)]
            pub struct Foo {
                pub x: u32,
            }
        }

        assert_eq!(offset_of!(sub::Foo, x), 0);
    }

    #[test]
    fn inside_generic_method() {
        struct Pair<T, U>(T, U);

        fn foo<T, U>(_: Pair<T, U>) -> usize {
            offset_of!(Pair<T, U>, 1)
        }

        assert_eq!(foo(Pair(0, 0)), 4);
    }

    #[cfg(feature = "unstable_const")]
    #[test]
    fn const_offset() {
        #[repr(C)]
        struct Foo {
            a: u32,
            b: [u8; 2],
            c: i64,
        }

        assert_eq!([0; offset_of!(Foo, b)].len(), 4);
    }
}
<|endoftext|>


<commit_before>use anyhow::Error;
use std::io;

pub fn is_file_nonexistant(err: &Error) -> bool {
    match err.downcast_ref::<io::Error>() {
        Some(err) if err.kind() == io::ErrorKind::NotFound => true,
        _ => false,
    }
}
<commit_msg>anup: Fix clippy warning<commit_after>use anyhow::Error;
use std::io;

pub fn is_file_nonexistant(err: &Error) -> bool {
    matches!(err.downcast_ref::<io::Error>(), Some(err) if err.kind() == io::ErrorKind::NotFound)
}
<|endoftext|>


<commit_before>// External modules:
use darwin_rs::{Individual, SimulationBuilder, Population, PopulationBuilder};
use image;
use image::{GenericImage, FilterType};
use rand::Rng;
use rand;

// Internal modules:
use config::PanolutionConfig;

#[derive(Clone)]
pub struct ImageArrangement {
    file_name: String, // TODO: Share path between individuals
    // TODO: Add image and share it, so it doesn't have to be re-loaded every time
    pos_x: u64,
    pos_y: u64,
    rotation: f64,
    // TODO: add more image operations
}

#[derive(Clone)]
pub struct Solution {
    arrangement: Vec<ImageArrangement>,
}

fn make_all_populations(num_of_individuals: u32, num_of_populations: u32, initial_solution: &Solution) -> Vec<Population<Solution>> {
    let mut result = Vec::new();

    let mut initial_population = Vec::new();

    for _ in 0..num_of_individuals {
        initial_population.push(initial_solution.clone());
    }

    for i in 0..num_of_populations {
        let pop = PopulationBuilder::<Solution>::new()
            .set_id(i + 1)
            .initial_population(&initial_population)
            .reset_limit_end(0)
            .increasing_mutation_rate()
            .finalize().unwrap();

        result.push(pop);
    }

    result
}

impl Individual for Solution {
    fn mutate(&mut self) {
        let mut rng = rand::thread_rng();
        let num_of_operations: u8 = 4;

        let index1: usize = rng.gen_range(0, self.arrangement.len());

        // Probably use this create and enums:
        // https://github.com/andersk/enum_primitive-rs

        let operation: u8 = rng.gen_range(0, num_of_operations);

        match operation {
            0 => {
                // Change image order
                let mut index2: usize = rng.gen_range(0, self.arrangement.len());
                while index1 == index2 {
                    index2 = rng.gen_range(0, self.arrangement.len());
                }

                self.arrangement.swap(index1, index2);
            },
            1 => {
                // Move x
                self.arrangement[index1].pos_x = self.arrangement[index1].pos_x + (rng.gen_range(0, 3) - 1);
            },
            2 => {
                // Move y
                self.arrangement[index1].pos_y = self.arrangement[index1].pos_y + (rng.gen_range(0, 3) - 1);
            },
            3 => {
                // Rotate
                let angle: f64 = ((rng.gen_range(0, 21) - 10) as f64) * 0.1;
                self.arrangement[index1].rotation = self.arrangement[index1].rotation + angle;
            },
            op => {
                warn!("mutate(): unknown operation: {}", op)
            }
        }
    }

    fn calculate_fitness(&mut self) -> f64 {
        0.0
    }

    fn reset(&mut self) {
        for arrangement in &mut self.arrangement {
            arrangement.pos_x = 0;
            arrangement.pos_y = 0;
            arrangement.rotation = 0.0;
        }
    }
}

fn run_darwin(solution: Solution, max_iteration: u32) -> Solution {
    info!("Run darwin with maximum number of iterations: {}", max_iteration);

    let pano = SimulationBuilder::<Solution>::new()
        .iterations(max_iteration)
        .threads(4) // TODO: Make this configurable
        .add_multiple_populations(make_all_populations(100, 8, &solution))
        .finalize();

    match pano {
        Err(e) => {
            error!("An error occured");

            for e in e.iter().skip(1) {
                error!("Caused by '{}'", e)
            }

            solution
        },
        Ok(mut pano_simulation) => {
            pano_simulation.run();

            info!("Total run time: {} ms", pano_simulation.total_time_in_ms);
            info!("Improvement factor: {}", pano_simulation.simulation_result.improvement_factor);
            info!("Number of iterations: {}", pano_simulation.simulation_result.iteration_counter);

            pano_simulation.simulation_result.fittest[0].individual.clone()
        }
    }
}

pub fn optimize(solution: Option<&Solution>, config: &PanolutionConfig, thumbnail_path: &Vec<String>) -> Solution {
    let mut result = Solution{ arrangement: Vec::new() };

    // Prepare data
    if let Some(solution) = solution {
        result.arrangement = solution.arrangement.iter().zip(thumbnail_path).map(|(arrangement, path)| ImageArrangement {
                file_name: path.clone(),
                pos_x: arrangement.pos_x,
                pos_y: arrangement.pos_y,
                rotation: arrangement.rotation,
            }
        ).collect();
    } else {
        result.arrangement = thumbnail_path.iter().map(|path| ImageArrangement {
                file_name: path.clone(),
                pos_x: 0,
                pos_y: 0,
                rotation: 0.0
            }
        ).collect();
    }

    run_darwin(result, config.max_iteration)
}
<commit_msg>calc intersection<commit_after>// External modules:
use darwin_rs::{Individual, SimulationBuilder, Population, PopulationBuilder};
use image;
use image::{GenericImage, FilterType, DynamicImage};
use rand::Rng;
use rand;

// Internal modules:
use config::PanolutionConfig;

#[derive(Clone)]
pub struct ImageArrangement {
    file_name: String, // TODO: Share path between individuals
    // TODO: Add image and share it, so it doesn't have to be re-loaded every time
    x: u32,
    y: u32,
    angle: f64,
    // TODO: add more image operations
}

#[derive(Clone)]
pub struct Solution {
    arrangement: Vec<ImageArrangement>,
}

#[derive(PartialEq, Eq, Debug)]
struct Rectangle {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
}

fn calc_intersection(x1: u32, x2: u32, y1: u32, y2: u32, w1: u32, w2: u32, h1: u32, h2: u32) -> (Rectangle, Rectangle) {
    // rect1 and rect2 refer to positions inside the images. Not the absolute positions.
    let mut rect1 = Rectangle{x: 0, y: 0, w: 0, h: 0};
    let mut rect2 = Rectangle{x: 0, y: 0, w: 0, h: 0};

    if x1 == x2 {
        rect1.x = 0;
        rect2.x = 0;

        if w1 < w2 {
            rect1.w = w1;
            rect2.w = w1;
        } else {
            rect1.w = w2;
            rect2.w = w2;
        }
    }

    if y1 == y2 {
        rect1.y = 0;
        rect2.y = 0;

        if h1 < h2 {
            rect1.h = h1;
            rect2.h = h1;
        } else {
            rect1.h = h2;
            rect2.h = h2;
        }
    }

    let dx = (x2 as i32 - x1 as i32).abs() as u32;
    let dy = (y2 as i32 - y1 as i32).abs() as u32;

    if x1 < x2 && dx < w1 {
        rect1.x = dx;
        rect1.w = w1 - dx;
        rect2.x = 0;
        rect2.w = rect1.w;
    }

    if x2 < x1 && dx < w2 {
        rect2.x = dx;
        rect2.w = w2 - dx;
        rect1.x = 0;
        rect1.w = rect2.w;
    }

    if y1 < y2 && dy < h1 {
        rect1.y = dy;
        rect1.h = h1 - dy;
        rect2.y = 0;
        rect2.h = rect1.h;
    }

    if y2 < y1 && dy < h2 {
        rect2.y = dy;
        rect2.h = h2 - dy;
        rect1.y = 0;
        rect1.h = rect2.h;
    }

    (rect1, rect2)
}

fn make_all_populations(num_of_individuals: u32, num_of_populations: u32, initial_solution: &Solution) -> Vec<Population<Solution>> {
    let mut result = Vec::new();

    let mut initial_population = Vec::new();

    for _ in 0..num_of_individuals {
        initial_population.push(initial_solution.clone());
    }

    for i in 0..num_of_populations {
        let pop = PopulationBuilder::<Solution>::new()
            .set_id(i + 1)
            .initial_population(&initial_population)
            .reset_limit_end(0)
            .increasing_mutation_rate()
            .finalize().unwrap();

        result.push(pop);
    }

    result
}

impl Individual for Solution {
    fn mutate(&mut self) {
        let mut rng = rand::thread_rng();
        let num_of_operations: u8 = 4;

        let index1: usize = rng.gen_range(0, self.arrangement.len());

        // Probably use this create and enums:
        // https://github.com/andersk/enum_primitive-rs

        let operation: u8 = rng.gen_range(0, num_of_operations);

        match operation {
            0 => {
                // Change image order
                let mut index2: usize = rng.gen_range(0, self.arrangement.len());
                while index1 == index2 {
                    index2 = rng.gen_range(0, self.arrangement.len());
                }

                self.arrangement.swap(index1, index2);
            },
            1 => {
                // Move x
                self.arrangement[index1].x = self.arrangement[index1].x + (rng.gen_range(0, 3) - 1);
            },
            2 => {
                // Move y
                self.arrangement[index1].y = self.arrangement[index1].y + (rng.gen_range(0, 3) - 1);
            },
            3 => {
                // Rotate
                let angle: f64 = ((rng.gen_range(0, 21) - 10) as f64) * 0.1;
                self.arrangement[index1].angle = self.arrangement[index1].angle + angle;
            },
            op => {
                warn!("mutate(): unknown operation: {}", op)
            }
        }
    }

    fn calculate_fitness(&mut self) -> f64 {
        let mut fitness = 0.0;

        for i in 0..self.arrangement.len() {
            let arrangement1 = &self.arrangement[i];
            let arrangement2 = &self.arrangement[i + 1];

            let image1 = image::open(&arrangement1.file_name).unwrap();
            let image2 = image::open(&arrangement2.file_name).unwrap();

            let (rect1, rect2) = calc_intersection(
                arrangement1.x, arrangement2.x, arrangement1.y, arrangement2.y,
                image1.width(), image2.width(), image1.height(), image2.height()
            );
        }

        fitness
    }

    fn reset(&mut self) {
        for arrangement in &mut self.arrangement {
            // Reset all image operation to original image
            arrangement.x = 0;
            arrangement.y = 0;
            arrangement.angle = 0.0;
        }
    }
}

fn run_darwin(solution: Solution, max_iteration: u32) -> Solution {
    info!("Run darwin with maximum number of iterations: {}", max_iteration);

    let pano = SimulationBuilder::<Solution>::new()
        .iterations(max_iteration)
        .threads(4) // TODO: Make this configurable
        .add_multiple_populations(make_all_populations(100, 8, &solution))
        .finalize();

    match pano {
        Err(e) => {
            error!("An error occured");

            for e in e.iter().skip(1) {
                error!("Caused by '{}'", e)
            }

            solution
        },
        Ok(mut pano_simulation) => {
            pano_simulation.run();

            info!("Total run time: {} ms", pano_simulation.total_time_in_ms);
            info!("Improvement factor: {}", pano_simulation.simulation_result.improvement_factor);
            info!("Number of iterations: {}", pano_simulation.simulation_result.iteration_counter);

            pano_simulation.simulation_result.fittest[0].individual.clone()
        }
    }
}

pub fn optimize(solution: Option<&Solution>, config: &PanolutionConfig, thumbnail_path: &Vec<String>) -> Solution {
    let mut result = Solution{ arrangement: Vec::new() };

    // Prepare data
    if let Some(solution) = solution {
        result.arrangement = solution.arrangement.iter().zip(thumbnail_path).map(|(arrangement, path)| ImageArrangement {
                file_name: path.clone(),
                x: arrangement.x,
                y: arrangement.y,
                angle: arrangement.angle,
            }
        ).collect();
    } else {
        result.arrangement = thumbnail_path.iter().map(|path| ImageArrangement {
                file_name: path.clone(),
                x: 0,
                y: 0,
                angle: 0.0
            }
        ).collect();
    }

    run_darwin(result, config.max_iteration)
}

#[cfg(test)]
mod test {
    use super::{calc_intersection, Rectangle};

    #[test]
    fn calc_intersection1() {
        let (r1, r2) = calc_intersection(0, 0, 0, 0, 10, 15, 20, 25);

        assert_eq!(r1, Rectangle{x: 0, y: 0, w: 10, h: 20});
        assert_eq!(r2, Rectangle{x: 0, y: 0, w: 10, h: 20});
    }

    #[test]
    fn calc_intersection2() {
        let (r1, r2) = calc_intersection(0, 0, 0, 0, 15, 10, 25, 20);

        assert_eq!(r1, Rectangle{x: 0, y: 0, w: 10, h: 20});
        assert_eq!(r2, Rectangle{x: 0, y: 0, w: 10, h: 20});
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use ffi;
use python::Python;
use std::{marker, rc, sync};

static START: sync::Once = sync::ONCE_INIT;

/// Prepares the use of Python in a free-threaded context.
///
/// If the Python interpreter is not already initialized, this function
/// will initialize it with disabled signal handling
/// (Python will not raise the `KeyboardInterrupt` exception).
/// Python signal handling depends on the notion of a 'main thread', which must be
/// the thread that initializes the Python interpreter.
///
/// If both the Python interpreter and Python threading are already initialized,
/// this function has no effect.
///
/// # Panic
/// If the Python interpreter is initialized but Python threading is not,
/// a panic occurs.
/// It is not possible to safely access the Python runtime unless the main
/// thread (the thread which originally initialized Python) also initializes
/// threading.
///
/// When writing an extension module, the `py_module_initializer!` macro
/// will ensure that Python threading is initialized.
///
pub fn prepare_freethreaded_python() {
    // Protect against race conditions when Python is not yet initialized
    // and multiple threads concurrently call 'prepare_freethreaded_python()'.
    // Note that we do not protect against concurrent initialization of the Python runtime
    // by other users of the Python C API.
    START.call_once(|| unsafe {
        if ffi::Py_IsInitialized() != 0 {
            // If Python is already initialized, we expect Python threading to also be initialized,
            // as we can't make the existing Python main thread acquire the GIL.
            assert!(ffi::PyEval_ThreadsInitialized() != 0);
        } else {
            #[cfg(feature = "python27-sys")]
            {
                // If Python isn't initialized yet, we expect that Python threading isn't initialized either.
                assert!(ffi::PyEval_ThreadsInitialized() == 0);
                // Note: starting with Python 3.2 it's no longer possible to initialize threading
                // without initializing Python; and in Python 3.7 PyEval_ThreadsInitialized() started
                // misbehaving when Python was not initialized yet.
            }
            // Initialize Python.
            // We use Py_InitializeEx() with initsigs=0 to disable Python signal handling.
            // Signal handling depends on the notion of a 'main thread', which doesn't exist in this case.
            // Note that the 'main thread' notion in Python isn't documented properly;
            // and running Python without one is not officially supported.
            ffi::Py_InitializeEx(0);
            ffi::PyEval_InitThreads();
            // PyEval_InitThreads() will acquire the GIL,
            // but we don't want to hold it at this point
            // (it's not acquired in the other code paths)
            // So immediately release the GIL:
            let _thread_state = ffi::PyEval_SaveThread();
            // Note that the PyThreadState returned by PyEval_SaveThread is also held in TLS by the Python runtime,
            // and will be restored by PyGILState_Ensure.
        }
    });
}

/// RAII type that represents the Global Interpreter Lock acquisition.
///
/// # Example
/// ```
/// use cpython::Python;
///
/// {
///     let gil_guard = Python::acquire_gil();
///     let py = gil_guard.python();
/// } // GIL is released when gil_guard is dropped
/// ```
#[must_use]
pub struct GILGuard {
    gstate: ffi::PyGILState_STATE,
    // hack to opt out of Send on stable rust, which doesn't
    // have negative impls
    no_send: marker::PhantomData<rc::Rc<()>>,
}

/// The Drop implementation for GILGuard will release the GIL.
impl Drop for GILGuard {
    fn drop(&mut self) {
        unsafe { ffi::PyGILState_Release(self.gstate) }
    }
}

impl GILGuard {
    /// Acquires the global interpreter lock, which allows access to the Python runtime.
    ///
    /// If the Python runtime is not already initialized, this function will initialize it.
    /// See [prepare_freethreaded_python()](fn.prepare_freethreaded_python.html) for details.
    pub fn acquire() -> GILGuard {
        if !cfg!(feature = "no-auto-initialize") {
            ::pythonrun::prepare_freethreaded_python();
        }
        let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
        GILGuard {
            gstate: gstate,
            no_send: marker::PhantomData,
        }
    }

    /// Retrieves the marker type that proves that the GIL was acquired.
    #[inline]
    pub fn python<'p>(&'p self) -> Python<'p> {
        unsafe { Python::assume_gil_acquired() }
    }
}

/// Mutex-like wrapper object for data that is protected by the Python GIL.
///
/// # Example
/// ```
/// use std::cell::Cell;
/// use cpython::{Python, GILProtected};
///
/// let data = GILProtected::new(Cell::new(0));
///
/// {
///     let gil_guard = Python::acquire_gil();
///     let cell = data.get(gil_guard.python());
///     cell.set(cell.get() + 1);
/// }
/// ```
pub struct GILProtected<T> {
    data: T,
}

unsafe impl<T: Send> Send for GILProtected<T> {}

/// Because `GILProtected` ensures that the contained data
/// is only accessed while the GIL is acquired,
/// it can implement `Sync` even if the contained data
/// does not.
unsafe impl<T: Send> Sync for GILProtected<T> {}

impl<T> GILProtected<T> {
    /// Creates a new instance of `GILProtected`.
    #[inline]
    #[cfg(feature = "nightly")]
    pub const fn new(data: T) -> GILProtected<T> {
        GILProtected { data: data }
    }

    /// Creates a new instance of `GILProtected`.
    #[inline]
    #[cfg(not(feature = "nightly"))]
    pub fn new(data: T) -> GILProtected<T> {
        GILProtected { data: data }
    }

    /// Returns a shared reference to the data stored in the `GILProtected`.
    ///
    /// Requires a `Python` instance as proof that the GIL is acquired.
    #[inline]
    pub fn get<'a>(&'a self, _py: Python<'a>) -> &'a T {
        &self.data
    }

    /// Consumes the `GILProtected`, returning the wrapped value.
    #[inline]
    pub fn into_inner(self) -> T {
        self.data
    }
}
<commit_msg>use std::sync::Once::new()<commit_after>// Copyright (c) 2015 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use ffi;
use python::Python;
use std::{marker, rc, sync};

static START: sync::Once = sync::Once::new();

/// Prepares the use of Python in a free-threaded context.
///
/// If the Python interpreter is not already initialized, this function
/// will initialize it with disabled signal handling
/// (Python will not raise the `KeyboardInterrupt` exception).
/// Python signal handling depends on the notion of a 'main thread', which must be
/// the thread that initializes the Python interpreter.
///
/// If both the Python interpreter and Python threading are already initialized,
/// this function has no effect.
///
/// # Panic
/// If the Python interpreter is initialized but Python threading is not,
/// a panic occurs.
/// It is not possible to safely access the Python runtime unless the main
/// thread (the thread which originally initialized Python) also initializes
/// threading.
///
/// When writing an extension module, the `py_module_initializer!` macro
/// will ensure that Python threading is initialized.
///
pub fn prepare_freethreaded_python() {
    // Protect against race conditions when Python is not yet initialized
    // and multiple threads concurrently call 'prepare_freethreaded_python()'.
    // Note that we do not protect against concurrent initialization of the Python runtime
    // by other users of the Python C API.
    START.call_once(|| unsafe {
        if ffi::Py_IsInitialized() != 0 {
            // If Python is already initialized, we expect Python threading to also be initialized,
            // as we can't make the existing Python main thread acquire the GIL.
            assert!(ffi::PyEval_ThreadsInitialized() != 0);
        } else {
            #[cfg(feature = "python27-sys")]
            {
                // If Python isn't initialized yet, we expect that Python threading isn't initialized either.
                assert!(ffi::PyEval_ThreadsInitialized() == 0);
                // Note: starting with Python 3.2 it's no longer possible to initialize threading
                // without initializing Python; and in Python 3.7 PyEval_ThreadsInitialized() started
                // misbehaving when Python was not initialized yet.
            }
            // Initialize Python.
            // We use Py_InitializeEx() with initsigs=0 to disable Python signal handling.
            // Signal handling depends on the notion of a 'main thread', which doesn't exist in this case.
            // Note that the 'main thread' notion in Python isn't documented properly;
            // and running Python without one is not officially supported.
            ffi::Py_InitializeEx(0);
            ffi::PyEval_InitThreads();
            // PyEval_InitThreads() will acquire the GIL,
            // but we don't want to hold it at this point
            // (it's not acquired in the other code paths)
            // So immediately release the GIL:
            let _thread_state = ffi::PyEval_SaveThread();
            // Note that the PyThreadState returned by PyEval_SaveThread is also held in TLS by the Python runtime,
            // and will be restored by PyGILState_Ensure.
        }
    });
}

/// RAII type that represents the Global Interpreter Lock acquisition.
///
/// # Example
/// ```
/// use cpython::Python;
///
/// {
///     let gil_guard = Python::acquire_gil();
///     let py = gil_guard.python();
/// } // GIL is released when gil_guard is dropped
/// ```
#[must_use]
pub struct GILGuard {
    gstate: ffi::PyGILState_STATE,
    // hack to opt out of Send on stable rust, which doesn't
    // have negative impls
    no_send: marker::PhantomData<rc::Rc<()>>,
}

/// The Drop implementation for GILGuard will release the GIL.
impl Drop for GILGuard {
    fn drop(&mut self) {
        unsafe { ffi::PyGILState_Release(self.gstate) }
    }
}

impl GILGuard {
    /// Acquires the global interpreter lock, which allows access to the Python runtime.
    ///
    /// If the Python runtime is not already initialized, this function will initialize it.
    /// See [prepare_freethreaded_python()](fn.prepare_freethreaded_python.html) for details.
    pub fn acquire() -> GILGuard {
        if !cfg!(feature = "no-auto-initialize") {
            ::pythonrun::prepare_freethreaded_python();
        }
        let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL
        GILGuard {
            gstate: gstate,
            no_send: marker::PhantomData,
        }
    }

    /// Retrieves the marker type that proves that the GIL was acquired.
    #[inline]
    pub fn python<'p>(&'p self) -> Python<'p> {
        unsafe { Python::assume_gil_acquired() }
    }
}

/// Mutex-like wrapper object for data that is protected by the Python GIL.
///
/// # Example
/// ```
/// use std::cell::Cell;
/// use cpython::{Python, GILProtected};
///
/// let data = GILProtected::new(Cell::new(0));
///
/// {
///     let gil_guard = Python::acquire_gil();
///     let cell = data.get(gil_guard.python());
///     cell.set(cell.get() + 1);
/// }
/// ```
pub struct GILProtected<T> {
    data: T,
}

unsafe impl<T: Send> Send for GILProtected<T> {}

/// Because `GILProtected` ensures that the contained data
/// is only accessed while the GIL is acquired,
/// it can implement `Sync` even if the contained data
/// does not.
unsafe impl<T: Send> Sync for GILProtected<T> {}

impl<T> GILProtected<T> {
    /// Creates a new instance of `GILProtected`.
    #[inline]
    #[cfg(feature = "nightly")]
    pub const fn new(data: T) -> GILProtected<T> {
        GILProtected { data: data }
    }

    /// Creates a new instance of `GILProtected`.
    #[inline]
    #[cfg(not(feature = "nightly"))]
    pub fn new(data: T) -> GILProtected<T> {
        GILProtected { data: data }
    }

    /// Returns a shared reference to the data stored in the `GILProtected`.
    ///
    /// Requires a `Python` instance as proof that the GIL is acquired.
    #[inline]
    pub fn get<'a>(&'a self, _py: Python<'a>) -> &'a T {
        &self.data
    }

    /// Consumes the `GILProtected`, returning the wrapped value.
    #[inline]
    pub fn into_inner(self) -> T {
        self.data
    }
}
<|endoftext|>


<commit_before>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;
mod symbols;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;
use symbols::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    let mut symbols_table = SymbolTable::new();
    parse_class(&tokens, 1, &mut symbols_table);

    if tokens[0].value != "class"
    {
        panic!("Unexpected token: {}: {}", tokens[0].value, tokens[0].name);
    }

    let (last_index, asm_string) = compile_class(&tokens, 1);
}

fn parse_class(tokens: &Vec<Token>, start_index: usize, symbols_table: &mut SymbolTable)
{
    let mut static_variables: Vec<(usize, usize)> = Vec::new();
    let mut static_methods: Vec<(usize, usize)> = Vec::new();
    let mut static_classes: Vec<(usize, usize)> = Vec::new();
    let mut non_static_variables: Vec<(usize, usize)> = Vec::new();
    let mut non_static_methods: Vec<(usize, usize)> = Vec::new();
    let mut non_static_classes: Vec<(usize, usize)> = Vec::new();

    println!("\n<------------ Parse Class --------------->");
    let mut min_value = 0;
    let mut skip_amount = 0;

    for (index, token) in tokens.iter().enumerate()
    {
        if min_value != 0
        {
            min_value -= 1;
            continue;
        }
        //Static Variable/Method/Class
        if token.name == "mod.access"
        {
            skip_amount = 3;
            if tokens[index + skip_amount].name.starts_with("operator")
            {
                println!("------Incoming Static Variable Decl!");

                let (low, high) = symbols_table.get_variable_locations(tokens, index + 1);
                symbols_table.static_variables.push((low, high));

                min_value =  low;
                min_value -= index;
            }
            else if tokens[index + 1].name.starts_with("construct")
            {
                if tokens[index + skip_amount].name.starts_with("control")
                {
                    println!("------Incoming Static Class Decl!");
                    min_value = find_outer_ending_brace(tokens, index);
                    static_classes.push((index + 2, min_value));
                    min_value -= index;
                }
                else
                {
                    panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
                }

            }
            else if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Static Method Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                static_methods.push((index + 1, min_value));
                min_value -=  index;
            }
            else
            {
                panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
            }

        }
        //Non-Static Variable/Method/Class
        else if token.name.starts_with("construct")
        {
            skip_amount = 2;
            if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Non-Static Class Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                non_static_classes.push((index + 1, min_value));
                min_value = 0;
            }
            else
            {
                panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
            }
        }
        //Non-Static Variable/Method/Class
        else if token.name == "type"
        {
            skip_amount = 2;

            if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Non-Static Method Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                non_static_methods.push((index, min_value));
                min_value -= index;
                //check for control
            }
            else if tokens[index + skip_amount].name.starts_with("operator")
            {
                println!("------Incoming Non-Static Variable Decl!");
                min_value =  find_next_semicolon(tokens, index);
                non_static_variables.push((index, min_value));
                min_value -= index;
            }
        }
        println!("\tIndex: {} | Token -> {} : {}", index, token.value, token.name );
        //deal with parameters
    }
    println!("\n<---------------- Static Variables --------------->");
    for &(start, end) in symbols_table.static_variables.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Static Classes ----------------->");
    for &(start, end) in static_classes.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Static Methods ----------------->");
    for &(start, end) in static_methods.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Variables --------------->");
    for &(start, end) in non_static_variables.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Classes ----------------->");
    for &(start, end) in non_static_classes.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Methods ----------------->");
    for &(start, end) in non_static_methods.iter()
    {
        println!("Start/End {}/{}", start, end);
    }
    println!("\n");
}

fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            if token.name.ends_with("access")
            {
                continue;
            }
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            if token.name.ends_with("package")
            {
                continue;
            }
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn compile_arithmetic_statement(tokens: &Vec<Token>, start: usize, temp_registers: (&str, &str), var_registers: (&str, &str), load_registers: (&str, &str)) -> (String, usize)
{
    let mut compiled_code = String::new();
    if tokens[start].value.starts_with("literal")
    {
        compiled_code.push_str("li ");
        compiled_code.push_str(temp_registers.0);
        compiled_code.push_str(", ");
        compiled_code.push_str(&*tokens[start].value);
        compiled_code.push_str("\n");
    }

    let mut index = start;
    while tokens[index].value != ";"
    {
        while tokens[index].name == "control" // ignore parenthesis
        {
            index += 1;
        }
        if !tokens[index].name.starts_with("operator")
        {
            let current_token = &tokens[index];
            panic!("Unexpected token while parsing arithmetic statement: {}: {}", current_token.value, current_token.name);
        }

        let operator = &tokens[index];
        while tokens[index].name == "control" // ignore parenthesis
        {
            index += 1;
        }
        let operand = &tokens[index + 1];
        if operand.name.starts_with("literal")
        {
            // TODO: use immediate operators
            compiled_code.push_str("li ");
            compiled_code.push_str(temp_registers.1);
            compiled_code.push_str(", ");
            compiled_code.push_str(&*operand.value);
            compiled_code.push_str("\n");
        }
        else if operand.name.starts_with("identifier")
        {
            // TODO: lookup memory location from symbols table
        }

        let line = compile_arithmetic_operation(operator, temp_registers, temp_registers.0);
        compiled_code.push_str(&*line);
        index += 2;
    }

    (compiled_code, index + 1)
}

fn compile_arithmetic_operation(operator: &Token, operand_registers: (&str, &str), result_register: &str) -> String
{
    let mut compiled_code = String::new();

    if operator.name != "operator.binary"
    {
        panic!("Unsupported operator: {}: {}", operator.name, operator.value);
    }
    else if operator.value == "+"
    {
        compiled_code.push_str("addu ");
    }
    else if operator.value == "-"
    {
        compiled_code.push_str("subu ");
    }
    else if operator.value == "*"
    {
        compiled_code.push_str("mullo ");
    }
    else
    {
        panic!("Unsupported operator: {}: {}", operator.name, operator.value);
    }

    compiled_code.push_str(result_register);
    compiled_code.push_str(", ");
    compiled_code.push_str(operand_registers.0);
    compiled_code.push_str(", ");
    compiled_code.push_str(operand_registers.1);
    compiled_code.push_str("\n");

    compiled_code
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}

fn find_outer_ending_brace(tokens: &Vec<Token>, start: usize) -> usize
{
    let mut open_braces = 0;

    for(index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == "{"
        {
            open_braces += 1;
        }
        else if token.value == "}"
        {
            open_braces -= 1;
            if open_braces == 0
            {
                return index + start;
            }
        }
    }

    return 0;
}
<commit_msg>Includes<commit_after>extern crate regex;

mod matching;
mod support;
mod tokens;
mod lexer;
mod files;
mod parser;
mod symbols;
mod symbol_table;

use std::vec::Vec;
use tokens::*;
use lexer::*;
use parser::*;
use symbols::*;
use symbol_table::*;

fn main()
{
    let source_file = "sampleData/BasicArithmatic.java";
    let lex_output_file = "sampleData/output/stable/BasicArithmatic.java.lexed";
    let preprocessed_output_file = "sampleData/output/stable/BasicArithmatic.java.preprocessed";

    let mut tokens: Vec<Token> = lex_file(source_file);

    println!("\n\nFound Tokens:");
    tokens.print_to(lex_output_file, true);

    remove_meta(&mut tokens);
    println!("\n\nPerged Tokens:");
    tokens.print_to(preprocessed_output_file, true);

    let mut symbols_table = SymbolTable::new();
    parse_class(&tokens, 1, &mut symbols_table);

    if tokens[0].value != "class"
    {
        panic!("Unexpected token: {}: {}", tokens[0].value, tokens[0].name);
    }

    let (last_index, asm_string) = compile_class(&tokens, 1);
}

fn parse_class(tokens: &Vec<Token>, start_index: usize, symbols_table: &mut SymbolTable)
{
    let mut static_variables: Vec<(usize, usize)> = Vec::new();
    let mut static_methods: Vec<(usize, usize)> = Vec::new();
    let mut static_classes: Vec<(usize, usize)> = Vec::new();
    let mut non_static_variables: Vec<(usize, usize)> = Vec::new();
    let mut non_static_methods: Vec<(usize, usize)> = Vec::new();
    let mut non_static_classes: Vec<(usize, usize)> = Vec::new();

    println!("\n<------------ Parse Class --------------->");
    let mut min_value = 0;
    let mut skip_amount = 0;

    for (index, token) in tokens.iter().enumerate()
    {
        if min_value != 0
        {
            min_value -= 1;
            continue;
        }
        //Static Variable/Method/Class
        if token.name == "mod.access"
        {
            skip_amount = 3;
            if tokens[index + skip_amount].name.starts_with("operator")
            {
                println!("------Incoming Static Variable Decl!");

                let (low, high) = symbols_table.get_variable_locations(tokens, index + 1);
                symbols_table.static_variables.push((low, high));

                min_value =  low;
                min_value -= index;
            }
            else if tokens[index + 1].name.starts_with("construct")
            {
                if tokens[index + skip_amount].name.starts_with("control")
                {
                    println!("------Incoming Static Class Decl!");
                    min_value = find_outer_ending_brace(tokens, index);
                    static_classes.push((index + 2, min_value));
                    min_value -= index;
                }
                else
                {
                    panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
                }

            }
            else if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Static Method Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                static_methods.push((index + 1, min_value));
                min_value -=  index;
            }
            else
            {
                panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
            }

        }
        //Non-Static Variable/Method/Class
        else if token.name.starts_with("construct")
        {
            skip_amount = 2;
            if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Non-Static Class Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                non_static_classes.push((index + 1, min_value));
                min_value = 0;
            }
            else
            {
                panic!("Unsupported or Unexpected token: {} + {}.", tokens[index + skip_amount].value, tokens[index + skip_amount].name);
            }
        }
        //Non-Static Variable/Method/Class
        else if token.name == "type"
        {
            skip_amount = 2;

            if tokens[index + skip_amount].name.starts_with("control")
            {
                println!("------Incoming Non-Static Method Decl!");
                min_value = find_outer_ending_brace(tokens, index);
                non_static_methods.push((index, min_value));
                min_value -= index;
                //check for control
            }
            else if tokens[index + skip_amount].name.starts_with("operator")
            {
                println!("------Incoming Non-Static Variable Decl!");
                min_value =  find_next_semicolon(tokens, index);
                non_static_variables.push((index, min_value));
                min_value -= index;
            }
        }
        println!("\tIndex: {} | Token -> {} : {}", index, token.value, token.name );
        //deal with parameters
    }
    println!("\n<---------------- Static Variables --------------->");
    for &(start, end) in symbols_table.static_variables.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Static Classes ----------------->");
    for &(start, end) in static_classes.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Static Methods ----------------->");
    for &(start, end) in static_methods.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Variables --------------->");
    for &(start, end) in non_static_variables.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Classes ----------------->");
    for &(start, end) in non_static_classes.iter()
    {
        println!("Start/End {}/{}", start, end);
    }

    println!("\n<---------------- Non-Static Methods ----------------->");
    for &(start, end) in non_static_methods.iter()
    {
        println!("Start/End {}/{}", start, end);
    }
    println!("\n");
}

fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

fn remove_meta(tokens: &mut Vec<Token>)
{
    // Indecies of tokens vector to be removed
    let mut invalid_indecies: Vec<usize> = Vec::new();

    let mut min_index: usize = 0;
    for (index, token) in tokens.iter().enumerate()
    {
        // Allow forward skipping (by setting min_index)
        if index < min_index
        {
            invalid_indecies.push(index);
        }
        // Remove imports
        else if token.name == "special.import"
        {
            invalid_indecies.push(index);
            min_index = index + 2; // skip the next token (semi-colon)
        }
        // Remove comments
        else if token.name.starts_with("comment")
        {
            invalid_indecies.push(index);
        }
        // Remove all modifiers (public, private, volatile, transient, static, etc.)
        else if token.name.starts_with("mod")
        {
            if token.name.ends_with("access")
            {
                continue;
            }
            invalid_indecies.push(index);
        }
        // Remove package declarations
        else if token.name == "special.package"
        {
            if token.name.ends_with("package")
            {
                continue;
            }
            invalid_indecies.push(index);
            min_index = find_next_semicolon(tokens, index) + 1;
        }
    }

    // count := how many indecies have already been removed
    // index := the index in the original tokens vector that should be removed
    for (count, index) in invalid_indecies.iter().enumerate()
    {
        // "index" refers to the index before any others were removed. Therefore, it must be offset by the number of removed tokens
        tokens.remove(index - count);
    }
}

fn compile_arithmetic_statement(tokens: &Vec<Token>, start: usize, temp_registers: (&str, &str), var_registers: (&str, &str), load_registers: (&str, &str)) -> (String, usize)
{
    let mut compiled_code = String::new();
    if tokens[start].value.starts_with("literal")
    {
        compiled_code.push_str("li ");
        compiled_code.push_str(temp_registers.0);
        compiled_code.push_str(", ");
        compiled_code.push_str(&*tokens[start].value);
        compiled_code.push_str("\n");
    }

    let mut index = start;
    while tokens[index].value != ";"
    {
        while tokens[index].name == "control" // ignore parenthesis
        {
            index += 1;
        }
        if !tokens[index].name.starts_with("operator")
        {
            let current_token = &tokens[index];
            panic!("Unexpected token while parsing arithmetic statement: {}: {}", current_token.value, current_token.name);
        }

        let operator = &tokens[index];
        while tokens[index].name == "control" // ignore parenthesis
        {
            index += 1;
        }
        let operand = &tokens[index + 1];
        if operand.name.starts_with("literal")
        {
            // TODO: use immediate operators
            compiled_code.push_str("li ");
            compiled_code.push_str(temp_registers.1);
            compiled_code.push_str(", ");
            compiled_code.push_str(&*operand.value);
            compiled_code.push_str("\n");
        }
        else if operand.name.starts_with("identifier")
        {
            // TODO: lookup memory location from symbols table

            // TODO: parse method calls
        }

        let line = compile_arithmetic_operation(operator, temp_registers, temp_registers.0);
        compiled_code.push_str(&*line);
        index += 2;
    }

    (compiled_code, index + 1)
}

fn compile_arithmetic_operation(operator: &Token, operand_registers: (&str, &str), result_register: &str) -> String
{
    let mut compiled_code = String::new();

    if operator.name != "operator.binary"
    {
        panic!("Unsupported operator: {}: {}", operator.name, operator.value);
    }
    else if operator.value == "+"
    {
        compiled_code.push_str("addu ");
    }
    else if operator.value == "-"
    {
        compiled_code.push_str("subu ");
    }
    else if operator.value == "*"
    {
        compiled_code.push_str("mullo ");
    }
    else
    {
        panic!("Unsupported operator: {}: {}", operator.name, operator.value);
    }

    compiled_code.push_str(result_register);
    compiled_code.push_str(", ");
    compiled_code.push_str(operand_registers.0);
    compiled_code.push_str(", ");
    compiled_code.push_str(operand_registers.1);
    compiled_code.push_str("\n");

    compiled_code
}

fn find_next_semicolon(tokens: &Vec<Token>, start: usize) -> usize
{
    for (index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == ";" { return index + start; }
    }

    return 0;
}

fn find_outer_ending_brace(tokens: &Vec<Token>, start: usize) -> usize
{
    let mut open_braces = 0;

    for(index, token) in tokens[start..].iter().enumerate()
    {
        if token.value == "{"
        {
            open_braces += 1;
        }
        else if token.value == "}"
        {
            open_braces -= 1;
            if open_braces == 0
            {
                return index + start;
            }
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>pub mod sentiment {
    use std::collections::HashMap;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::{self, BufReader};
    use std::path::Path;

    pub struct Analizer {
        wordlist: HashMap<String, i8>
    }

    impl Analizer {
        pub fn analyze(self, s: &str) -> f32 {
            let tokens = s.split(" ");
            let word_count = tokens.clone().count();

            let score = tokens
                .map(|word| word.to_string().to_lowercase())
                .map(|word| match self.wordlist.get(&word) {
                    Some(word_score) => *word_score,
                    None => 0 as i8,
                })
                .fold(0, |sum, curr| sum+curr );

            return score as f32 / word_count as f32;
        }
    }

    pub fn new(path: String) -> Analizer {
        let mut wordlist = HashMap::new();

        let mut f = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}", path, why),
            Ok(f) => f,
        };

        let f = BufReader::new(f);

        for line in f.lines() {
            let l = line.unwrap();
            let parts = l.split("\t").collect::<Vec<&str>>();

            let word = parts[0].to_string();
            let score = parts[1].parse::<i8>().unwrap();

            wordlist.insert(word, score);
        }

        return Analizer {
            wordlist: wordlist
        }
    }
}

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

    #[test]
    fn sentiment_test() {
        /*
           analyze("I am happy"); //Score: 3, Comparative: 1
           analyze("I am so happy"); //Score: 6, Comparative: 1.5
           analyze("I am extremely happy"); //Score: 12, Comparative: 3
           analyze("I am really sad"); //Score: -4, Comparative: -1
*/
        let mut analizer = sentiment::new("/Users/coornail/rust/ircbot/src/wordlist.txt".to_string());
        assert!(analizer.analyze("Hey you worthless scumbag") == -1.5)
    }
}
<commit_msg>Clean up sentiment.rs<commit_after>pub mod sentiment {
    use std::collections::HashMap;
    use std::fs::File;
    use std::io::prelude::*;
    use std::io::BufReader;

    pub struct Analizer {
        wordlist: HashMap<String, i8>
    }

    impl Analizer {
        pub fn analyze(&self, s: &str) -> f32 {
            let tokens = s.split(" ");
            let word_count = tokens.clone().count();

            let score = tokens
                .map(|word| word.to_string().to_lowercase())
                .map(|word| match self.wordlist.get(&word) {
                    Some(word_score) => *word_score,
                    None => 0 as i8,
                })
                .fold(0, |sum, curr| sum+curr );

            return score as f32 / word_count as f32;
        }
    }

    pub fn new(path: String) -> Analizer {
        let mut wordlist = HashMap::new();

        let f = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}", path, why),
            Ok(f) => f,
        };

        let f = BufReader::new(f);

        for line in f.lines() {
            let l = line.unwrap();
            let parts = l.split("\t").collect::<Vec<&str>>();

            let word = parts[0].to_string();
            let score = parts[1].parse::<i8>().unwrap();

            wordlist.insert(word, score);
        }

        return Analizer {
            wordlist: wordlist
        }
    }
}

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

    #[test]
    fn sentiment_test() {
        let analizer = sentiment::new("/Users/coornail/rust/ircbot/src/wordlist.txt".to_string());
        assert!(analizer.analyze("Hey you worthless scumbag") == -1.5);
        assert!(analizer.analyze("I am happy") == 1 as f32);
        assert!(analizer.analyze("I am so happy") == 0.75);
        assert!(analizer.analyze("I am extremely happy") == 0.75 as f32);
        assert!(analizer.analyze("I am really sad") == -0.5 as f32);
    }
}
<|endoftext|>


<commit_before>pub mod foreign_items;
pub mod intrinsics;
pub mod tls;
pub mod dlsym;
pub mod env;

use rustc::{ty, mir};

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn find_fn(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, Tag>],
        dest: Option<PlaceTy<'tcx, Tag>>,
        ret: Option<mir::BasicBlock>,
    ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
        let this = self.eval_context_mut();
        trace!("eval_fn_call: {:#?}, {:?}", instance, dest.map(|place| *place));

        // First, run the common hooks also supported by CTFE.
        if this.hook_fn(instance, args, dest)? {
            this.goto_block(ret)?;
            return Ok(None);
        }
        // There are some more lang items we want to hook that CTFE does not hook (yet).
        if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {

            let n = {
                let ptr = this.read_scalar(args[0])?.not_undef()?.assert_ptr();
                let align = this.force_bits(
                    this.read_scalar(args[1])?.not_undef()?,
                    this.pointer_size()
                )? as usize;

                let stride = this.memory().get(ptr.alloc_id)?.align.bytes() as usize;
                // if the allocation alignment is at least the required alignment, we use the
                // libcore implementation
                if stride >= align {
                    ((stride + ptr.offset.bytes() as usize) as *const ())
                        .align_offset(align) as u128
                } else {
                    u128::max_value()
                }
            };

            let dest = dest.unwrap();
            let n = this.truncate(n, dest.layout);
            this.write_scalar(Scalar::from_uint(n, dest.layout.size), dest)?;
            this.goto_block(ret)?;
            return Ok(None);
        }

        // Try to see if we can do something about foreign items.
        if this.tcx.is_foreign_item(instance.def_id()) {
            // An external function that we cannot find MIR for, but we can still run enough
            // of them to make miri viable.
            this.emulate_foreign_item(instance.def_id(), args, dest, ret)?;
            // `goto_block` already handled.
            return Ok(None);
        }

        // Otherwise, load the MIR.
        Ok(Some(this.load_mir(instance.def, None)?))
    }
}
<commit_msg>Use force_ptr instead of assert_ptr<commit_after>pub mod foreign_items;
pub mod intrinsics;
pub mod tls;
pub mod dlsym;
pub mod env;

use rustc::{ty, mir};

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn find_fn(
        &mut self,
        instance: ty::Instance<'tcx>,
        args: &[OpTy<'tcx, Tag>],
        dest: Option<PlaceTy<'tcx, Tag>>,
        ret: Option<mir::BasicBlock>,
    ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
        let this = self.eval_context_mut();
        trace!("eval_fn_call: {:#?}, {:?}", instance, dest.map(|place| *place));

        // First, run the common hooks also supported by CTFE.
        if this.hook_fn(instance, args, dest)? {
            this.goto_block(ret)?;
            return Ok(None);
        }
        // There are some more lang items we want to hook that CTFE does not hook (yet).
        if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {

            let n = {
                let ptr = this.force_ptr(this.read_scalar(args[0])?.not_undef()?)?;
                let align = this.force_bits(
                    this.read_scalar(args[1])?.not_undef()?,
                    this.pointer_size()
                )? as usize;

                let stride = this.memory().get(ptr.alloc_id)?.align.bytes() as usize;
                // if the allocation alignment is at least the required alignment, we use the
                // libcore implementation
                if stride >= align {
                    ((stride + ptr.offset.bytes() as usize) as *const ())
                        .align_offset(align) as u128
                } else {
                    u128::max_value()
                }
            };

            let dest = dest.unwrap();
            let n = this.truncate(n, dest.layout);
            this.write_scalar(Scalar::from_uint(n, dest.layout.size), dest)?;
            this.goto_block(ret)?;
            return Ok(None);
        }

        // Try to see if we can do something about foreign items.
        if this.tcx.is_foreign_item(instance.def_id()) {
            // An external function that we cannot find MIR for, but we can still run enough
            // of them to make miri viable.
            this.emulate_foreign_item(instance.def_id(), args, dest, ret)?;
            // `goto_block` already handled.
            return Ok(None);
        }

        // Otherwise, load the MIR.
        Ok(Some(this.load_mir(instance.def, None)?))
    }
}
<|endoftext|>


<commit_before>use descartes::{N, P2, WithUniqueOrthogonal};
use util::random::{Rng};
use michelangelo::{Vertex, Mesh};

use super::{Lot, BuildingStyle};

pub fn ideal_lot_shape(building_style: BuildingStyle) -> (f32, f32) {
    match building_style {
        BuildingStyle::FamilyHouse => (20.0, 30.0),
        BuildingStyle::GroceryShop => (15.0, 20.0),
        BuildingStyle::Bakery => (20.0, 30.0),
        BuildingStyle::Mill => (20.0, 30.0),
        BuildingStyle::Field => (50.0, 100.0),
        BuildingStyle::NeighboringTownConnection => (5.0, 5.0),
    }
}

#[derive(Compact, Clone)]
pub struct BuildingMesh {
    pub wall: Mesh,
    pub brick_roof: Mesh,
    pub flat_roof: Mesh,
    pub field: Mesh,
}

pub fn build_building<R: Rng>(
    lot: &Lot,
    building_type: BuildingStyle,
    rng: &mut R,
) -> BuildingMesh {
    let building_position = lot.center_point();
    let building_orientation = lot.best_road_connection().1;

    let (main_footprint, entrance_footprint) = generate_house_footprint(lot, rng);

    match building_type {
        BuildingStyle::FamilyHouse => {
            let height = 3.0 + 3.0 * rng.gen::<f32>();
            let entrance_height = 2.0 + rng.gen::<f32>();

            let (roof_brick_mesh, roof_wall_mesh) =
                main_footprint.open_gable_roof_mesh(height, 0.3);
            let (entrance_roof_brick_mesh, entrance_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(entrance_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height)
                    + roof_wall_mesh
                    + entrance_roof_wall_mesh,
                brick_roof: roof_brick_mesh + entrance_roof_brick_mesh,
                flat_roof: Mesh::empty(),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::GroceryShop => {
            let height = 3.0 + rng.gen::<f32>();
            let entrance_height = height - 0.7;

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height),
                brick_roof: Mesh::empty(),
                flat_roof: main_footprint.flat_roof_mesh(height)
                    + entrance_footprint.flat_roof_mesh(entrance_height),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::Field => BuildingMesh {
            wall: Mesh::empty(),
            brick_roof: Mesh::empty(),
            flat_roof: Mesh::empty(),
            field: Mesh::from_area(&lot.area),
        },
        BuildingStyle::Mill => {
            let height = 3.0 + rng.gen::<f32>();
            let tower_height = 5.0 + rng.gen::<f32>();

            let (roof_brick_mesh, roof_wall_mesh) =
                main_footprint.open_gable_roof_mesh(height, 0.3);
            let (tower_roof_brick_mesh, tower_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(tower_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(tower_height)
                    + roof_wall_mesh
                    + tower_roof_wall_mesh,
                brick_roof: Mesh::empty(),
                flat_roof: roof_brick_mesh + tower_roof_brick_mesh,
                field: Mesh::empty(),
            }
        }
        BuildingStyle::Bakery => {
            let height = 3.0 + rng.gen::<f32>();
            let entrance_height = height;

            let (entrance_roof_brick_mesh, entrance_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(entrance_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height)
                    + entrance_roof_wall_mesh,
                brick_roof: entrance_roof_brick_mesh,
                flat_roof: main_footprint.flat_roof_mesh(height),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::NeighboringTownConnection => {
            let length = 20.0;
            let building_orientation_orth = building_orientation.orthogonal();

            let vertices = vec![
                building_position - length / 4.0 * building_orientation,
                building_position + length / 2.0 * building_orientation_orth,
                building_position + length / 4.0 * building_orientation,
                building_position - length / 2.0 * building_orientation_orth,
            ].into_iter()
            .map(|v| Vertex {
                position: [v.x, v.y, 3.0],
            }).collect();

            let indices = vec![0, 1, 2, 2, 3, 0];

            BuildingMesh {
                wall: Mesh::new(vertices, indices),
                brick_roof: Mesh::empty(),
                flat_roof: Mesh::empty(),
                field: Mesh::empty(),
            }
        }
    }
}

pub struct Footprint {
    back_right: P2,
    back_left: P2,
    front_right: P2,
    front_left: P2,
}

impl Footprint {
    fn wall_mesh(&self, wall_height: N) -> Mesh {
        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, 0.0],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, 0.0],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, 0.0],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, 0.0],
            },
            Vertex {
                position: [self.back_right.x, self.back_right.y, wall_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, wall_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, wall_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, wall_height],
            },
        ];

        let indices = vec![
            0, 1, 4, 1, 5, 4, 1, 2, 5, 2, 6, 5, 2, 3, 6, 3, 7, 6, 3, 0, 7, 0, 4, 7,
        ];

        Mesh::new(vertices, indices)
    }

    fn flat_roof_mesh(&self, base_height: N) -> Mesh {
        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, base_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, base_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, base_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, base_height],
            },
        ];

        let indices = vec![0, 1, 3, 1, 2, 3];

        Mesh::new(vertices, indices)
    }

    fn open_gable_roof_mesh(&self, base_height: N, angle: N) -> (Mesh, Mesh) {
        let roof_height = (self.back_right - self.front_right).norm() * angle.sin();
        let mid_right = (self.back_right + self.front_right.coords) / 2.0;
        let mid_left = (self.back_left + self.front_left.coords) / 2.0;

        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, base_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, base_height],
            },
            Vertex {
                position: [mid_left.x, mid_left.y, base_height + roof_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, base_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, base_height],
            },
            Vertex {
                position: [mid_right.x, mid_right.y, base_height + roof_height],
            },
        ];

        let roof_indices = vec![0, 1, 2, 2, 5, 0, 2, 3, 4, 4, 5, 2];

        let wall_indices = vec![1, 2, 3, 4, 5, 0];

        (
            Mesh::new(vertices.clone(), roof_indices),
            Mesh::new(vertices, wall_indices),
        )
    }

    fn scale(&self, factor: f32) -> Footprint {
        let center = P2::from_coordinates(
            (self.back_left.coords
                + self.back_right.coords
                + self.front_left.coords
                + self.front_right.coords)
                / 4.0,
        );

        Footprint {
            back_left: center + factor * (self.back_left - center),
            back_right: center + factor * (self.back_right - center),
            front_left: center + factor * (self.front_left - center),
            front_right: center + factor * (self.front_right - center),
        }
    }
}

pub fn generate_house_footprint<R: Rng>(lot: &Lot, rng: &mut R) -> (Footprint, Footprint) {
    let building_position = lot.center_point();
    let building_orientation = lot.best_road_connection().1;
    let building_orientation_orth = building_orientation.orthogonal();

    let footprint_width = 10.0 + rng.gen::<f32>() * 7.0;
    let footprint_depth = 7.0 + rng.gen::<f32>() * 5.0;

    let entrance_position = building_position
        + building_orientation * (0.5 - 1.0 * rng.gen::<f32>()) * footprint_width
        - building_orientation_orth * (rng.gen::<f32>() * 0.3 + 0.1) * footprint_depth;
    let entrance_width = 5.0 + rng.gen::<f32>() * 4.0;
    let entrance_depth = 3.0 + rng.gen::<f32>() * 3.0;

    (
        Footprint {
            back_right: building_position + building_orientation * footprint_width / 2.0
                - building_orientation_orth * footprint_depth / 2.0,
            back_left: building_position
                - building_orientation * footprint_width / 2.0
                - building_orientation_orth * footprint_depth / 2.0,
            front_left: building_position - building_orientation * footprint_width / 2.0
                + building_orientation_orth * footprint_depth / 2.0,
            front_right: building_position
                + building_orientation * footprint_width / 2.0
                + building_orientation_orth * footprint_depth / 2.0,
        },
        Footprint {
            back_right: entrance_position
                + building_orientation_orth * entrance_width / 2.0
                + building_orientation * entrance_depth / 2.0,
            back_left: entrance_position - building_orientation_orth * entrance_width / 2.0
                + building_orientation * entrance_depth / 2.0,
            front_left: entrance_position
                - building_orientation_orth * entrance_width / 2.0
                - building_orientation * entrance_depth / 2.0,
            front_right: entrance_position + building_orientation_orth * entrance_width / 2.0
                - building_orientation * entrance_depth / 2.0,
        },
    )
}
<commit_msg>Orient buildings properly towards the roads<commit_after>use descartes::{N, P2, WithUniqueOrthogonal};
use util::random::{Rng};
use michelangelo::{Vertex, Mesh};

use super::{Lot, BuildingStyle};

pub fn ideal_lot_shape(building_style: BuildingStyle) -> (f32, f32) {
    match building_style {
        BuildingStyle::FamilyHouse => (20.0, 30.0),
        BuildingStyle::GroceryShop => (15.0, 20.0),
        BuildingStyle::Bakery => (20.0, 30.0),
        BuildingStyle::Mill => (20.0, 30.0),
        BuildingStyle::Field => (50.0, 100.0),
        BuildingStyle::NeighboringTownConnection => (5.0, 5.0),
    }
}

#[derive(Compact, Clone)]
pub struct BuildingMesh {
    pub wall: Mesh,
    pub brick_roof: Mesh,
    pub flat_roof: Mesh,
    pub field: Mesh,
}

pub fn build_building<R: Rng>(
    lot: &Lot,
    building_type: BuildingStyle,
    rng: &mut R,
) -> BuildingMesh {
    let building_position = lot.center_point();
    let building_orientation = lot.best_road_connection().1;

    let (main_footprint, entrance_footprint) = generate_house_footprint(lot, rng);

    match building_type {
        BuildingStyle::FamilyHouse => {
            let height = 3.0 + 3.0 * rng.gen::<f32>();
            let entrance_height = 2.0 + rng.gen::<f32>();

            let (roof_brick_mesh, roof_wall_mesh) =
                main_footprint.open_gable_roof_mesh(height, 0.3);
            let (entrance_roof_brick_mesh, entrance_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(entrance_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height)
                    + roof_wall_mesh
                    + entrance_roof_wall_mesh,
                brick_roof: roof_brick_mesh + entrance_roof_brick_mesh,
                flat_roof: Mesh::empty(),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::GroceryShop => {
            let height = 3.0 + rng.gen::<f32>();
            let entrance_height = height - 0.7;

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height),
                brick_roof: Mesh::empty(),
                flat_roof: main_footprint.flat_roof_mesh(height)
                    + entrance_footprint.flat_roof_mesh(entrance_height),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::Field => BuildingMesh {
            wall: Mesh::empty(),
            brick_roof: Mesh::empty(),
            flat_roof: Mesh::empty(),
            field: Mesh::from_area(&lot.area),
        },
        BuildingStyle::Mill => {
            let height = 3.0 + rng.gen::<f32>();
            let tower_height = 5.0 + rng.gen::<f32>();

            let (roof_brick_mesh, roof_wall_mesh) =
                main_footprint.open_gable_roof_mesh(height, 0.3);
            let (tower_roof_brick_mesh, tower_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(tower_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(tower_height)
                    + roof_wall_mesh
                    + tower_roof_wall_mesh,
                brick_roof: Mesh::empty(),
                flat_roof: roof_brick_mesh + tower_roof_brick_mesh,
                field: Mesh::empty(),
            }
        }
        BuildingStyle::Bakery => {
            let height = 3.0 + rng.gen::<f32>();
            let entrance_height = height;

            let (entrance_roof_brick_mesh, entrance_roof_wall_mesh) =
                entrance_footprint.open_gable_roof_mesh(entrance_height, 0.3);

            BuildingMesh {
                wall: main_footprint.wall_mesh(height)
                    + entrance_footprint.wall_mesh(entrance_height)
                    + entrance_roof_wall_mesh,
                brick_roof: entrance_roof_brick_mesh,
                flat_roof: main_footprint.flat_roof_mesh(height),
                field: Mesh::empty(),
            }
        }
        BuildingStyle::NeighboringTownConnection => {
            let length = 20.0;
            let building_orientation_orth = building_orientation.orthogonal();

            let vertices = vec![
                building_position - length / 4.0 * building_orientation,
                building_position + length / 2.0 * building_orientation_orth,
                building_position + length / 4.0 * building_orientation,
                building_position - length / 2.0 * building_orientation_orth,
            ].into_iter()
            .map(|v| Vertex {
                position: [v.x, v.y, 3.0],
            }).collect();

            let indices = vec![0, 1, 2, 2, 3, 0];

            BuildingMesh {
                wall: Mesh::new(vertices, indices),
                brick_roof: Mesh::empty(),
                flat_roof: Mesh::empty(),
                field: Mesh::empty(),
            }
        }
    }
}

pub struct Footprint {
    back_right: P2,
    back_left: P2,
    front_right: P2,
    front_left: P2,
}

impl Footprint {
    fn wall_mesh(&self, wall_height: N) -> Mesh {
        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, 0.0],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, 0.0],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, 0.0],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, 0.0],
            },
            Vertex {
                position: [self.back_right.x, self.back_right.y, wall_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, wall_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, wall_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, wall_height],
            },
        ];

        let indices = vec![
            0, 1, 4, 1, 5, 4, 1, 2, 5, 2, 6, 5, 2, 3, 6, 3, 7, 6, 3, 0, 7, 0, 4, 7,
        ];

        Mesh::new(vertices, indices)
    }

    fn flat_roof_mesh(&self, base_height: N) -> Mesh {
        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, base_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, base_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, base_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, base_height],
            },
        ];

        let indices = vec![0, 1, 3, 1, 2, 3];

        Mesh::new(vertices, indices)
    }

    fn open_gable_roof_mesh(&self, base_height: N, angle: N) -> (Mesh, Mesh) {
        let roof_height = (self.back_right - self.front_right).norm() * angle.sin();
        let mid_right = (self.back_right + self.front_right.coords) / 2.0;
        let mid_left = (self.back_left + self.front_left.coords) / 2.0;

        let vertices = vec![
            Vertex {
                position: [self.back_right.x, self.back_right.y, base_height],
            },
            Vertex {
                position: [self.back_left.x, self.back_left.y, base_height],
            },
            Vertex {
                position: [mid_left.x, mid_left.y, base_height + roof_height],
            },
            Vertex {
                position: [self.front_left.x, self.front_left.y, base_height],
            },
            Vertex {
                position: [self.front_right.x, self.front_right.y, base_height],
            },
            Vertex {
                position: [mid_right.x, mid_right.y, base_height + roof_height],
            },
        ];

        let roof_indices = vec![0, 1, 2, 2, 5, 0, 2, 3, 4, 4, 5, 2];

        let wall_indices = vec![1, 2, 3, 4, 5, 0];

        (
            Mesh::new(vertices.clone(), roof_indices),
            Mesh::new(vertices, wall_indices),
        )
    }

    fn scale(&self, factor: f32) -> Footprint {
        let center = P2::from_coordinates(
            (self.back_left.coords
                + self.back_right.coords
                + self.front_left.coords
                + self.front_right.coords)
                / 4.0,
        );

        Footprint {
            back_left: center + factor * (self.back_left - center),
            back_right: center + factor * (self.back_right - center),
            front_left: center + factor * (self.front_left - center),
            front_right: center + factor * (self.front_right - center),
        }
    }
}

pub fn generate_house_footprint<R: Rng>(lot: &Lot, rng: &mut R) -> (Footprint, Footprint) {
    let building_position = lot.center_point();
    let building_orientation = lot.best_road_connection().1;
    let building_orientation_orth = building_orientation.orthogonal();

    let footprint_width = 10.0 + rng.gen::<f32>() * 7.0;
    let footprint_depth = 7.0 + rng.gen::<f32>() * 5.0;

    let entrance_position = building_position
        + building_orientation_orth * (0.5 - 1.0 * rng.gen::<f32>()) * footprint_width
        + building_orientation * (rng.gen::<f32>() * 0.3 + 0.1) * footprint_depth;
    let entrance_width = 5.0 + rng.gen::<f32>() * 4.0;
    let entrance_depth = 3.0 + rng.gen::<f32>() * 3.0;

    (
        Footprint {
            back_right: building_position + building_orientation_orth * footprint_width / 2.0
                - building_orientation * footprint_depth / 2.0,
            back_left: building_position
                - building_orientation_orth * footprint_width / 2.0
                - building_orientation * footprint_depth / 2.0,
            front_left: building_position - building_orientation_orth * footprint_width / 2.0
                + building_orientation * footprint_depth / 2.0,
            front_right: building_position
                + building_orientation_orth * footprint_width / 2.0
                + building_orientation * footprint_depth / 2.0,
        },
        Footprint {
            back_right: entrance_position
                + building_orientation * entrance_width / 2.0
                + building_orientation_orth * entrance_depth / 2.0,
            back_left: entrance_position - building_orientation * entrance_width / 2.0
                + building_orientation_orth * entrance_depth / 2.0,
            front_left: entrance_position
                - building_orientation * entrance_width / 2.0
                - building_orientation_orth * entrance_depth / 2.0,
            front_right: entrance_position + building_orientation * entrance_width / 2.0
                - building_orientation_orth * entrance_depth / 2.0,
        },
    )
}
<|endoftext|>