<commit_before>use std::iter;
use super::heap::{Heap, HeapAllocable, BytesRef};

/// dbj2 hash function
fn djb2(key: &[u8]) -> u64 {
    let mut state: u64 = 5381;
    for &b in key {
        state = (state << 5).wrapping_add(state).wrapping_add(b as u64);
    }
    state
}

impl Default for BytesRef {
    fn default() -> BytesRef {
        BytesRef {
            start: 0u32,
            stop: 0u32,
        }
    }
}

/// `KeyValue` is the item stored in the hash table.
/// The key is actually a `BytesRef` object stored in an external heap.
/// The `value_addr` also points to an address in the heap.
///
/// The key and the value are actually stored contiguously.
/// For this reason, the (start, stop) information is actually redundant
/// and can be simplified in the future
#[derive(Copy, Clone, Default)]
struct KeyValue {
    key: BytesRef,
    value_addr: u32,
}

impl KeyValue {
    fn is_empty(&self) -> bool {
        self.key.stop == 0u32
    }
}

pub enum Entry {
    Vacant(usize),
    Occupied(u32),
}

/// Customized `HashMap` with string keys
///
/// This `HashMap` takes String as keys. Keys are
/// stored in a user defined heap.
///
/// The quirky API has the benefit of avoiding
/// the computation of the hash of the key twice,
/// or copying the key as long as there is no insert.
///
pub struct HashMap<'a> {
    table: Box<[KeyValue]>,
    heap: &'a Heap,
    mask: usize,
    occupied: Vec<usize>,
}

struct QuadraticProbing {
    hash: usize,
    i: usize,
    mask: usize,
}

impl QuadraticProbing {
    fn compute(key: &[u8], mask: usize) -> QuadraticProbing {
        let hash = djb2(key) as usize;
        QuadraticProbing {
            hash: hash,
            i: 0,
            mask: mask,
        }
    }

    #[inline]
    fn next_probe(&mut self) -> usize {
        self.i += 1;
        (self.hash + self.i * self.i) & self.mask
    }
}

impl<'a> HashMap<'a> {
    pub fn new(num_bucket_power_of_2: usize, heap: &'a Heap) -> HashMap<'a> {
        let table_size = 1 << num_bucket_power_of_2;
        let table: Vec<KeyValue> = iter::repeat(KeyValue::default()).take(table_size).collect();
        HashMap {
            table: table.into_boxed_slice(),
            heap: heap,
            mask: table_size - 1,
            occupied: Vec::with_capacity(table_size / 2),
        }
    }

    fn probe(&self, key: &[u8]) -> QuadraticProbing {
        QuadraticProbing::compute(key, self.mask)
    }

    pub fn is_saturated(&self) -> bool {
        self.table.len() < self.occupied.len() * 10
    }

    fn get_key(&self, bytes_ref: BytesRef) -> &[u8] {
        self.heap.get_slice(bytes_ref)
    }

    pub fn set_bucket(&mut self, key_bytes: &[u8], bucket: usize, addr: u32) -> u32 {
        self.occupied.push(bucket);
        self.table[bucket] = KeyValue {
            key: self.heap.allocate_and_set(key_bytes),
            value_addr: addr,
        };
        addr
    }

    pub fn iter<'b: 'a>(&'b self) -> impl Iterator<Item = (&'a [u8], u32)> + 'b {
        let heap: &'a Heap = self.heap;
        let table: &'b [KeyValue] = &self.table;
        self.occupied
            .iter()
            .cloned()
            .map(move |bucket: usize| {
                     let kv = table[bucket];
                     let addr = kv.value_addr;
                     (heap.get_slice(kv.key), addr)
                 })
    }

    pub fn get_or_create<S: AsRef<[u8]>, V: HeapAllocable>(&mut self, key: S) -> &mut V {
        let entry = self.lookup(key.as_ref());
        match entry {
            Entry::Occupied(addr) => self.heap.get_mut_ref(addr),
            Entry::Vacant(bucket) => {
                let (addr, val): (u32, &mut V) = self.heap.allocate_object();
                self.set_bucket(key.as_ref(), bucket, addr);
                val
            }
        }
    }

    pub fn lookup<S: AsRef<[u8]>>(&self, key: S) -> Entry {
        let key_bytes: &[u8] = key.as_ref();
        let mut probe = self.probe(key_bytes);
        loop {
            let bucket = probe.next_probe();
            let kv: KeyValue = self.table[bucket];
            if kv.is_empty() {
                return Entry::Vacant(bucket);
            }
            if self.get_key(kv.key) == key_bytes {
                return Entry::Occupied(kv.value_addr);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use super::super::heap::{Heap, HeapAllocable};
    use super::djb2;
    use test::Bencher;
    use std::collections::hash_map::DefaultHasher;
    use std::hash::Hasher;

    struct TestValue {
        val: u32,
        _addr: u32,
    }

    impl HeapAllocable for TestValue {
        fn with_addr(addr: u32) -> TestValue {
            TestValue {
                val: 0u32,
                _addr: addr,
            }
        }
    }

    #[test]
    fn test_hash_map() {
        let heap = Heap::with_capacity(2_000_000);
        let mut hash_map: HashMap = HashMap::new(18, &heap);
        {
            let v: &mut TestValue = hash_map.get_or_create("abc");
            assert_eq!(v.val, 0u32);
            v.val = 3u32;
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abcd");
            assert_eq!(v.val, 0u32);
            v.val = 4u32;
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abc");
            assert_eq!(v.val, 3u32);
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abcd");
            assert_eq!(v.val, 4u32);
        }
        let mut iter_values = hash_map.iter();
        {
            let (_, addr) = iter_values.next().unwrap();
            let val: &TestValue = heap.get_ref(addr);
            assert_eq!(val.val, 3u32);
        }
        {
            let (_, addr) = iter_values.next().unwrap();
            let val: &TestValue = heap.get_ref(addr);
            assert_eq!(val.val, 4u32);
        }
        assert!(iter_values.next().is_none());
    }

    #[bench]
    fn bench_djb2(bench: &mut Bencher) {
        let v = String::from("abwer");
        bench.iter(|| djb2(v.as_bytes()));
    }

    #[bench]
    fn bench_siphasher(bench: &mut Bencher) {
        let v = String::from("abwer");
        bench.iter(|| {
                       let mut h = DefaultHasher::new();
                       h.write(v.as_bytes());
                       h.finish()
                   });
    }

}
<commit_msg>issue/188 Using murmurhash<commit_after>use std::iter;
use super::heap::{Heap, HeapAllocable, BytesRef};

mod murmurhash2 {

    const SEED: u32 = 3_242_157_231u32;

    #[inline(always)]
    pub fn murmurhash2(key: &[u8]) -> u32 {
        let mut key_ptr: *const u32 = key.as_ptr() as *const u32;
        let m: u32 = 0x5bd1e995;
        let r = 24;
        let len = key.len() as u32;

        let mut h: u32 = SEED ^ len;
        let num_blocks = len >> 2;
        for _ in 0..num_blocks {
            let mut k: u32 = unsafe { *key_ptr };
            k = k.wrapping_mul(m);
            k ^= k >> r;
            k = k.wrapping_mul(m);
            k = k.wrapping_mul(m);
            h ^= k;
            key_ptr = key_ptr.wrapping_offset(1);
        }

        // Handle the last few bytes of the input array
        let remaining = len & 3;
        let key_ptr_u8: *const u8 = key_ptr as *const u8;
        match remaining {
            3 => {
                h ^= unsafe { *key_ptr_u8.wrapping_offset(2) as u32 } << 16;
                h ^= unsafe { *key_ptr_u8.wrapping_offset(1) as u32 } << 8;
                h ^= unsafe { *key_ptr_u8 as u32 };
                h = h.wrapping_mul(m);
            }
            2 => {
                h ^= unsafe { *key_ptr_u8.wrapping_offset(1) as u32 } << 8;
                h ^= unsafe { *key_ptr_u8 as u32 };
                h = h.wrapping_mul(m);
            }
            1 => {
                h ^= unsafe { *key_ptr_u8 as u32 };
                h = h.wrapping_mul(m);
            }
            _ => {}
        }
        h ^= h >> 13;
        h = h.wrapping_mul(m);
        h ^ (h >> 15)
    }
}

impl Default for BytesRef {
    fn default() -> BytesRef {
        BytesRef {
            start: 0u32,
            stop: 0u32,
        }
    }
}

/// `KeyValue` is the item stored in the hash table.
/// The key is actually a `BytesRef` object stored in an external heap.
/// The `value_addr` also points to an address in the heap.
///
/// The key and the value are actually stored contiguously.
/// For this reason, the (start, stop) information is actually redundant
/// and can be simplified in the future
#[derive(Copy, Clone, Default)]
struct KeyValue {
    key: BytesRef,
    value_addr: u32,
}

impl KeyValue {
    fn is_empty(&self) -> bool {
        self.key.stop == 0u32
    }
}

pub enum Entry {
    Vacant(usize),
    Occupied(u32),
}

/// Customized `HashMap` with string keys
///
/// This `HashMap` takes String as keys. Keys are
/// stored in a user defined heap.
///
/// The quirky API has the benefit of avoiding
/// the computation of the hash of the key twice,
/// or copying the key as long as there is no insert.
///
pub struct HashMap<'a> {
    table: Box<[KeyValue]>,
    heap: &'a Heap,
    mask: usize,
    occupied: Vec<usize>,
}

struct QuadraticProbing {
    hash: usize,
    i: usize,
    mask: usize,
}

impl QuadraticProbing {
    fn compute(key: &[u8], mask: usize) -> QuadraticProbing {
        let hash = murmurhash2::murmurhash2(key) as usize;
        QuadraticProbing {
            hash: hash,
            i: 0,
            mask: mask,
        }
    }

    #[inline]
    fn next_probe(&mut self) -> usize {
        self.i += 1;
        (self.hash + self.i * self.i) & self.mask
    }
}

impl<'a> HashMap<'a> {
    pub fn new(num_bucket_power_of_2: usize, heap: &'a Heap) -> HashMap<'a> {
        let table_size = 1 << num_bucket_power_of_2;
        let table: Vec<KeyValue> = iter::repeat(KeyValue::default()).take(table_size).collect();
        HashMap {
            table: table.into_boxed_slice(),
            heap: heap,
            mask: table_size - 1,
            occupied: Vec::with_capacity(table_size / 2),
        }
    }

    fn probe(&self, key: &[u8]) -> QuadraticProbing {
        QuadraticProbing::compute(key, self.mask)
    }

    pub fn is_saturated(&self) -> bool {
        self.table.len() < self.occupied.len() * 10
    }

    fn get_key(&self, bytes_ref: BytesRef) -> &[u8] {
        self.heap.get_slice(bytes_ref)
    }

    pub fn set_bucket(&mut self, key_bytes: &[u8], bucket: usize, addr: u32) -> u32 {
        self.occupied.push(bucket);
        self.table[bucket] = KeyValue {
            key: self.heap.allocate_and_set(key_bytes),
            value_addr: addr,
        };
        addr
    }

    pub fn iter<'b: 'a>(&'b self) -> impl Iterator<Item = (&'a [u8], u32)> + 'b {
        let heap: &'a Heap = self.heap;
        let table: &'b [KeyValue] = &self.table;
        self.occupied
            .iter()
            .cloned()
            .map(move |bucket: usize| {
                     let kv = table[bucket];
                     let addr = kv.value_addr;
                     (heap.get_slice(kv.key), addr)
                 })
    }

    pub fn get_or_create<S: AsRef<[u8]>, V: HeapAllocable>(&mut self, key: S) -> &mut V {
        let entry = self.lookup(key.as_ref());
        match entry {
            Entry::Occupied(addr) => self.heap.get_mut_ref(addr),
            Entry::Vacant(bucket) => {
                let (addr, val): (u32, &mut V) = self.heap.allocate_object();
                self.set_bucket(key.as_ref(), bucket, addr);
                val
            }
        }
    }

    pub fn lookup<S: AsRef<[u8]>>(&self, key: S) -> Entry {
        let key_bytes: &[u8] = key.as_ref();
        let mut probe = self.probe(key_bytes);
        loop {
            let bucket = probe.next_probe();
            let kv: KeyValue = self.table[bucket];
            if kv.is_empty() {
                return Entry::Vacant(bucket);
            }
            if self.get_key(kv.key) == key_bytes {
                return Entry::Occupied(kv.value_addr);
            }
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use super::super::heap::{Heap, HeapAllocable};
    use super::murmurhash2::murmurhash2;
    use test::Bencher;
    use std::collections::HashSet;
    use std::collections::hash_map::DefaultHasher;
    use std::hash::Hasher;

    struct TestValue {
        val: u32,
        _addr: u32,
    }

    impl HeapAllocable for TestValue {
        fn with_addr(addr: u32) -> TestValue {
            TestValue {
                val: 0u32,
                _addr: addr,
            }
        }
    }

    #[test]
    fn test_hash_map() {
        let heap = Heap::with_capacity(2_000_000);
        let mut hash_map: HashMap = HashMap::new(18, &heap);
        {
            let v: &mut TestValue = hash_map.get_or_create("abc");
            assert_eq!(v.val, 0u32);
            v.val = 3u32;
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abcd");
            assert_eq!(v.val, 0u32);
            v.val = 4u32;
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abc");
            assert_eq!(v.val, 3u32);
        }
        {
            let v: &mut TestValue = hash_map.get_or_create("abcd");
            assert_eq!(v.val, 4u32);
        }
        let mut iter_values = hash_map.iter();
        {
            let (_, addr) = iter_values.next().unwrap();
            let val: &TestValue = heap.get_ref(addr);
            assert_eq!(val.val, 3u32);
        }
        {
            let (_, addr) = iter_values.next().unwrap();
            let val: &TestValue = heap.get_ref(addr);
            assert_eq!(val.val, 4u32);
        }
        assert!(iter_values.next().is_none());
    }

    #[test]
    fn test_murmur() {
        let s1 = "abcdef";
        let s2 = "abcdeg";
        for i in 0..5 {
            assert_eq!(murmurhash2(&s1[i..5].as_bytes()),
                       murmurhash2(&s2[i..5].as_bytes()));
        }
    }

    #[test]
    fn test_murmur_collisions() {
        let mut set: HashSet<u32> = HashSet::default();
        for i in 0..10_000 {
            let s = format!("hash{}", i);
            let hash = murmurhash2(s.as_bytes());
            set.insert(hash);
        }
        assert_eq!(set.len(), 10_000);
    }

    #[bench]
    fn bench_murmurhash_2(b: &mut Bencher) {
        let keys: Vec<&'static str> =
            vec!["wer qwe qwe qwe ", "werbq weqweqwe2 ", "weraq weqweqwe3 "];
        b.iter(|| {
                   keys.iter()
                       .map(|&s| s.as_bytes())
                       .map(murmurhash2::murmurhash2)
                       .map(|h| h as u64)
                       .last()
                       .unwrap()
               });
    }

    #[bench]
    fn bench_siphasher(bench: &mut Bencher) {
        let v = String::from("abwer");
        bench.iter(|| {
                       let mut h = DefaultHasher::new();
                       h.write(v.as_bytes());
                       h.finish()
                   });
    }

}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use context::ContextMap;
use dispatcher::demux::Demultiplexer;
use dispatcher::request::{RequestHandle, Request};
use reactor::{Event, EventDemultiplexer, EventHandler, Reactor};
use dispatcher::response::ResponseSender;

pub struct RequestReactor {
    handlers: BTreeMap<RequestHandle, Box<EventHandler<Request, ContextMap>>>,
    demultiplexer: Demultiplexer<Request>,
    context_map: ContextMap,
    responder: Box<ResponseSender>
}

impl RequestReactor {
    pub fn new(demultiplexer: Demultiplexer<Request>, context_map: ContextMap, responder: Box<ResponseSender>) -> RequestReactor {
        RequestReactor {
            demultiplexer: demultiplexer,
            context_map: context_map,
            handlers: BTreeMap::new(),
            responder: responder
        }
    }
}

impl Reactor<ContextMap> for RequestReactor {
    type Event = Request;
    fn handle_events(&mut self) {
        while let Some(request) = self.demultiplexer.select() {
            trace!("RequestReactor: got event");
            if let Some(handler) = self.handlers.get_mut(&request.handle()) {
                handler.handle_event(request, &mut self.context_map);
            } else {
                trace!("RequestReactor: no handler found for event");
            }
        }
    }
    fn register_handler(&mut self, handler: Box<EventHandler<Self::Event, ContextMap>>) {
        self.handlers.insert(handler.handle(), handler);
    }
    fn remove_handler_by_handle(&mut self, handler: &RequestHandle) {
        self.handlers.remove(handler);
    }
}
<commit_msg>RequestReactor: use higher-ranked lifetime<commit_after>use std::collections::BTreeMap;

use context::ContextMap;
use dispatcher::demux::Demultiplexer;
use dispatcher::request::{RequestHandle, Request};
use reactor::{Event, EventDemultiplexer, EventHandler, Reactor, SharedData};
use dispatcher::response::ResponseSender;

pub struct RequestReactor {
    handlers: BTreeMap<RequestHandle, Box<for<'a> EventHandler<Request, SharedData<'a>>>>,
    demultiplexer: Demultiplexer<Request>,
    context_map: ContextMap,
    responder: Box<ResponseSender>
}

impl RequestReactor {
    pub fn new(demultiplexer: Demultiplexer<Request>, context_map: ContextMap, responder: Box<ResponseSender>) -> RequestReactor {
        RequestReactor {
            demultiplexer: demultiplexer,
            context_map: context_map,
            handlers: BTreeMap::new(),
            responder: responder
        }
    }
}

impl Reactor for RequestReactor {
    type Event = Request;
    fn handle_events(&mut self) {
        let mut shared_data = SharedData::new(&mut self.context_map, &mut *self.responder);
        while let Some(request) = self.demultiplexer.select() {
            trace!("RequestReactor: got event");
            if let Some(handler) = self.handlers.get_mut(&request.handle()) {
                handler.handle_event(request, &mut shared_data);
            } else {
                trace!("RequestReactor: no handler found for event");
            }
        }
    }
    fn register_handler(&mut self, handler: Box<for<'a> EventHandler<Self::Event, SharedData<'a>>>) {
        self.handlers.insert(handler.handle(), handler);
    }
    fn remove_handler_by_handle(&mut self, handler: &RequestHandle) {
        self.handlers.remove(handler);
    }
}
<|endoftext|>


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

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

pub mod draw;
pub mod specialized;
<|endoftext|>


<commit_before>use std::rand::{self, Rng};
use std::ops::Slice;
use serialize::base64::{self, ToBase64};
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::thread_rng())
    }

    fn generate(r: &mut Rng) -> Nonce {
        let mut nonce = [0u8; 10];
        r.fill_bytes(nonce.as_mut_slice());
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8; 20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result.as_mut_slice());
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl Slice<uint, str> for Nonce {
    #[inline] fn as_slice_(&self) -> &str {
        match *self { Nonce(ref n) => n[] }
    }

    #[inline] fn slice_from_or_fail(&self, from: &uint) -> &str {
        match *self { Nonce(ref n) => n[*from..] }
    }

    #[inline] fn slice_to_or_fail(&self, to: &uint) -> &str {
        match *self { Nonce(ref n) => n[..*to] }
    }

    #[inline] fn slice_or_fail(&self, from: &uint, to: &uint) -> &str {
        match *self { Nonce(ref n) => n[*from..*to] }
    }
}

impl Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        self[]
    }
}
<commit_msg>nonce generate signature fix<commit_after>use std::rand::{self, Rng};
use std::ops::Slice;
use serialize::base64::{self, ToBase64};
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::thread_rng())
    }

    fn generate<R: Rng>(r: &mut R) -> Nonce {
        let mut nonce = [0u8; 10];
        r.fill_bytes(nonce.as_mut_slice());
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8; 20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result.as_mut_slice());
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl Slice<uint, str> for Nonce {
    #[inline] fn as_slice_(&self) -> &str {
        match *self { Nonce(ref n) => n[] }
    }

    #[inline] fn slice_from_or_fail(&self, from: &uint) -> &str {
        match *self { Nonce(ref n) => n[*from..] }
    }

    #[inline] fn slice_to_or_fail(&self, to: &uint) -> &str {
        match *self { Nonce(ref n) => n[..*to] }
    }

    #[inline] fn slice_or_fail(&self, from: &uint, to: &uint) -> &str {
        match *self { Nonce(ref n) => n[*from..*to] }
    }
}

impl Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        self[]
    }
}
<|endoftext|>


<commit_before>use core::cmp::{ Ord, Eq };
use core::ops::{ Add, Mul };
use core::num::{ Zero, One };

use common::bounded::{ Bounded };

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

pub trait Unwrap<T> {
    fn unwrap(&self) -> T;
}

pub struct Sum<T> { repr: T }
pub fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Zero+Add<T,T>+Copy> Monoid for Sum<T> {
    fn mempty() -> Sum<T> { Sum(Zero::zero()) }
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr + other.repr) }
}

impl<T: Copy> Unwrap<T> for Sum<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Sum<T> {
    fn eq(&self, other: &Sum<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: One+Mul<T,T>+Copy> Monoid for Prod<T> {
    fn mempty() -> Prod<T> { Prod(One::one()) }
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr * other.repr) }
}

impl<T: Copy> Unwrap<T> for Prod<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Eq for Prod<T> {
    fn eq(&self, other: &Prod<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Max<T> {
    fn mempty() -> Max<T> { Max(Bounded::min_value()) }
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Max<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Max<T> {
    fn eq(&self, other: &Max<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Min<T> {
    fn mempty() -> Min<T> { Min(Bounded::max_value()) }
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Min<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Min<T> {
    fn eq(&self, other: &Min<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy+Monoid>(v: &[T]) -> T {
    vec::foldl(Monoid::mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

pub fn merge<T: Copy + Ord, M: Copy + Monoid>(
    vec1: &[(T, M)], vec2: &[(T, M)]
) -> ~[(T, M)] {
    let (l1, l2) = (vec1.len(), vec2.len());

    let mut result = ~[];
    let mut (i1, i2) = (0, 0);
    while i1 < l1 && i2 < l2 {
        let (v1, m1) = vec1[i1];
        let (v2, m2) = vec2[i2];
        if v1 < v2 {
            result.push((v1, m1));
            i1 += 1;
            loop;
        }
        if v2 < v1 {
            result.push((v2, m2));
            i2 += 1;
            loop;
        }
        result.push((v1, m1.mappend(&m2)));
        i1 += 1;
        i2 += 1;
    }

    if i1 < l1 { result += vec1.slice(i1, l1); }
    if i2 < l2 { result += vec2.slice(i2, l2); }
    return result;
}

pub fn mergei<T: Copy+Ord, M: Copy+Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vecs.slice(0u, len / 2u));
        let post = mergei(vecs.slice(len / 2u, len));
        merge(pre, post)
      }
    }
}

pub fn merge_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>
    (vec1: &[(T, U)], vec2: &[(T, U)], f: &fn(U) -> M) -> ~[(T, MT)] {
    fn convert<T: Copy, U: Copy, M: Copy>(v: &[(T, U)], f: &fn(U) -> M) -> ~[(T, M)] {
        do v.map |tp| { (tp.first(), f(tp.second())) }
    }
    return merge(convert(vec1, f), convert(vec2, f)).map(|tp| (tp.first(), tp.second().unwrap()));
}

pub fn mergei_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>(vecs: &[~[(T, U)]], f: &fn(U) -> M) -> ~[(T, MT)] {
    return mergei(
        vecs.map(|v| v.map(|tp| (tp.first(), f(tp.second()))))
    ).map(|tp| (tp.first(), tp.second().unwrap()));
}

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

    fn to_sum<T: Copy, U: Copy>(tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = *tp;
        return (t, Sum(u));
    }

    fn to_max<T: Copy, U: Copy+Ord>(tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = *tp;
        return (t, Max(u));
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = ~[(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_sum), arg2.map(to_sum)),
                       result.map(to_sum));
            assert_eq!(merge_as(arg1, arg2, Sum), result);
        }

        {
            let result = ~[(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_max), arg2.map(to_max)),
                       result.map(to_max));
            assert_eq!(merge_as(arg1, arg2, Max),
                       result);
        }

        {
            let result = arg1.map(to_sum);
            assert_eq!(merge(result, []), result);
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert_eq!(merge([], []), result);
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[(1, 1), (2, 1)], ~[(1, 2), (3, 1)], ~[(-1, 3)]];
            let result = ~[(-1, 3), (1, 3), (2, 1), (3, 1)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[(1, 1)], ~[(1, 2)], ~[(1, 3)]];
            let result = ~[(1, 6)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[], ~[], ~[]];
            let result: ~[(int, int)] = ~[];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))),
                       result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum),
                       result);
        }
    }
}

<commit_msg>Add common::monoid::MergeMonoidIterator<commit_after>use core::util;
use core::cmp::{ Ord, Eq };
use core::ops::{ Add, Mul };
use core::num::{ Zero, One };
use core::iterator::{ Iterator };

use common::bounded::{ Bounded };

pub trait Monoid {
    fn mempty() -> Self;
    fn mappend(&self, other: &Self) -> Self;
}

pub trait Unwrap<T> {
    fn unwrap(&self) -> T;
}

pub struct Sum<T> { repr: T }
pub fn Sum<T>(val: T) -> Sum<T> { Sum { repr: val } }

impl<T: Zero+Add<T,T>+Copy> Monoid for Sum<T> {
    fn mempty() -> Sum<T> { Sum(Zero::zero()) }
    fn mappend(&self, other: &Sum<T>) -> Sum<T> { Sum(self.repr + other.repr) }
}

impl<T: Copy> Unwrap<T> for Sum<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Sum<T> {
    fn eq(&self, other: &Sum<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Sum<T>) -> bool { self.repr != other.repr }
}

pub struct Prod<T> { repr: T }
pub fn Prod<T>(val: T) -> Prod<T> { Prod { repr: val }}

impl<T: One+Mul<T,T>+Copy> Monoid for Prod<T> {
    fn mempty() -> Prod<T> { Prod(One::one()) }
    fn mappend(&self, other: &Prod<T>) -> Prod<T> { Prod(self.repr * other.repr) }
}

impl<T: Copy> Unwrap<T> for Prod<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: cmp::Eq> Eq for Prod<T> {
    fn eq(&self, other: &Prod<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Prod<T>) -> bool { self.repr != other.repr }
}

pub struct Max<T> { repr: T }
pub fn Max<T>(val: T) -> Max<T> { Max{ repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Max<T> {
    fn mempty() -> Max<T> { Max(Bounded::min_value()) }
    fn mappend(&self, other: &Max<T>) -> Max<T> {
        if self.repr < other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Max<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Max<T> {
    fn eq(&self, other: &Max<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Max<T>) -> bool { self.repr != other.repr }
}

pub struct Min<T> { repr: T }
pub fn Min<T>(val: T) -> Min<T> { Min { repr: val } }

impl<T: Copy+Bounded+Ord> Monoid for Min<T> {
    fn mempty() -> Min<T> { Min(Bounded::max_value()) }
    fn mappend(&self, other: &Min<T>) -> Min<T> {
        if self.repr > other.repr { *other } else { *self }
    }
}

impl<T: Copy> Unwrap<T> for Min<T> {
    fn unwrap(&self) -> T { self.repr }
}

impl<T: Eq> Eq for Min<T> {
    fn eq(&self, other: &Min<T>) -> bool { self.repr == other.repr }
    fn ne(&self, other: &Min<T>) -> bool { self.repr != other.repr }
}

pub fn mconcat<T: Copy+Monoid>(v: &[T]) -> T {
    vec::foldl(Monoid::mempty(), v, |accum, elt| { elt.mappend(&accum) })
}

struct MergeMonoidIterator<V, T, U> {
    iter1: T,
    value1: Option<V>,
    iter2: U,
    value2: Option<V>
}

impl<V, T: Iterator<V>, U: Iterator<V>> MergeMonoidIterator<V, T, U> {
    pub fn new(iter1: T, iter2: U) -> MergeMonoidIterator<V, T, U> {
        MergeMonoidIterator { iter1: iter1, value1: None, iter2: iter2, value2: None }
    }
}

impl<K: TotalOrd, V: Monoid, T: Iterator<(K, V)>, U: Iterator<(K, V)>>
    Iterator<(K, V)> for MergeMonoidIterator<(K, V), T, U> {
    fn next(&mut self) -> Option<(K, V)> {
        fn return_val<V>(opt: &mut Option<V>) -> Option<V> {
            let mut result = None;
            util::swap(opt, &mut result);
            return result;
        }

        // Fill value if empty (if iter ends, set None)
        if self.value1.is_none() { self.value1 = self.iter1.next(); }
        if self.value2.is_none() { self.value2 = self.iter2.next(); }

        // If one value is None, returns anogher value (with setting None)
        if self.value1.is_none() { return return_val(&mut self.value2); }
        if self.value2.is_none() { return return_val(&mut self.value1); }

        // Returns smaller value
        let cmp = self.value1.get_ref().first_ref().cmp(self.value2.get_ref().first_ref());
        match cmp {
            Less    => { return return_val(&mut self.value1); }
            Greater => { return return_val(&mut self.value2); },
            Equal   => {
                let mut r1 = None, r2 = None;
                util::swap(&mut self.value1, &mut r1);
                util::swap(&mut self.value2, &mut r2);
                let ((k, v1), (_, v2)) = (r1.unwrap(), r2.unwrap());
                return Some((k, v1.mappend(&v2)));
            }
        }
    }
}

pub fn merge<T: Copy + Ord, M: Copy + Monoid>(
    vec1: &[(T, M)], vec2: &[(T, M)]
) -> ~[(T, M)] {
    let (l1, l2) = (vec1.len(), vec2.len());

    let mut result = ~[];
    let mut (i1, i2) = (0, 0);
    while i1 < l1 && i2 < l2 {
        let (v1, m1) = vec1[i1];
        let (v2, m2) = vec2[i2];
        if v1 < v2 {
            result.push((v1, m1));
            i1 += 1;
            loop;
        }
        if v2 < v1 {
            result.push((v2, m2));
            i2 += 1;
            loop;
        }
        result.push((v1, m1.mappend(&m2)));
        i1 += 1;
        i2 += 1;
    }

    if i1 < l1 { result += vec1.slice(i1, l1); }
    if i2 < l2 { result += vec2.slice(i2, l2); }
    return result;
}

pub fn mergei<T: Copy+Ord, M: Copy+Monoid>(vecs: &[~[(T, M)]]) -> ~[(T, M)] {
    return match vecs.len() {
      0u => ~[],
      1u => ~[] + vecs[0],
      len  => {
        let pre  = mergei(vecs.slice(0u, len / 2u));
        let post = mergei(vecs.slice(len / 2u, len));
        merge(pre, post)
      }
    }
}

pub fn merge_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>
    (vec1: &[(T, U)], vec2: &[(T, U)], f: &fn(U) -> M) -> ~[(T, MT)] {
    fn convert<T: Copy, U: Copy, M: Copy>(v: &[(T, U)], f: &fn(U) -> M) -> ~[(T, M)] {
        do v.map |tp| { (tp.first(), f(tp.second())) }
    }
    return merge(convert(vec1, f), convert(vec2, f)).map(|tp| (tp.first(), tp.second().unwrap()));
}

pub fn mergei_as<T: Copy+Ord, U: Copy, MT, M: Copy+Monoid+Unwrap<MT>>(vecs: &[~[(T, U)]], f: &fn(U) -> M) -> ~[(T, MT)] {
    return mergei(
        vecs.map(|v| v.map(|tp| (tp.first(), f(tp.second()))))
    ).map(|tp| (tp.first(), tp.second().unwrap()));
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::iterator::{ IteratorUtil };
    use common::extvec;

    fn to_sum<T, U>(&tp: &(T, U)) -> (T, Sum<U>) {
        let (t, u) = tp;
        return (t, Sum(u));
    }

    fn to_max<T, U>(&tp: &(T, U)) -> (T, Max<U>) {
        let (t, u) = tp;
        return (t, Max(u));
    }

    #[test]
    fn test_merge_monoid_iterator() {
        fn check<M: Monoid + Eq>(v1: &[(int, int)],
                                 v2: &[(int, int)],
                                 f: &fn(&(int, int)) -> (int, M),
                                 result: &[(int, int)]) {
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v1.iter().transform(f),
                                                           v2.iter().transform(f))),
                result.map(f));
            assert_eq!(
                extvec::from_iter(MergeMonoidIterator::new(v2.iter().transform(f),
                                                           v1.iter().transform(f))),
                result.map(f));
        }

        let v1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let v2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        check(v1, v2, to_sum, [(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)]);
        check(v1, v2, to_max, [(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)]);

        check(v1, [], to_sum, v1);
        check([], [], to_sum, []);
    }

    #[test]
    fn test_merge() {
        let arg1 = [(1, 1), (3, 1), (4, 1), (6, 1)];
        let arg2 = [(1, 2), (2, 1), (4, 1), (7, 2)];

        {
            let result = ~[(1, 3), (2, 1), (3, 1), (4, 2), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_sum), arg2.map(to_sum)),
                       result.map(to_sum));
            assert_eq!(merge_as(arg1, arg2, Sum), result);
        }

        {
            let result = ~[(1, 2), (2, 1), (3, 1), (4, 1), (6, 1), (7, 2)];
            assert_eq!(merge(arg1.map(to_max), arg2.map(to_max)),
                       result.map(to_max));
            assert_eq!(merge_as(arg1, arg2, Max),
                       result);
        }

        {
            let result = arg1.map(to_sum);
            assert_eq!(merge(result, []), result);
        }

        {
            let result: ~[(int, Sum<int>)] = ~[];
            assert_eq!(merge([], []), result);
        }
    }

    #[test]
    fn test_mergei() {
        {
            let arg = [~[(1, 1), (2, 1)], ~[(1, 2), (3, 1)], ~[(-1, 3)]];
            let result = ~[(-1, 3), (1, 3), (2, 1), (3, 1)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[(1, 1)], ~[(1, 2)], ~[(1, 3)]];
            let result = ~[(1, 6)];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))), result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum), result);
        }

        {
            let arg = [~[], ~[], ~[]];
            let result: ~[(int, int)] = ~[];
            assert_eq!(mergei(arg.map(|v| v.map(to_sum))),
                       result.map(to_sum));
            assert_eq!(mergei_as(arg, Sum),
                       result);
        }
    }
}

<|endoftext|>


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

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use cmp::Ordering;
use convert::TryFrom;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

/// The error type returned when a conversion from a slice to an array fails.
#[unstable(feature = "try_from", issue = "33417")]
#[derive(Debug, Copy, Clone)]
pub struct TryFromSliceError(());

impl fmt::Display for TryFromSliceError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.__description())
    }
}

impl TryFromSliceError {
    #[inline]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        "could not convert slice to array"
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[unstable(feature = "try_from", issue = "33417")]
            impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_ptr() as *const [T; $N];
                        unsafe { Ok(&*ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[unstable(feature = "try_from", issue = "33417")]
            impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_mut_ptr() as *mut [T; $N];
                        unsafe { Ok(&mut *ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<commit_msg>Make TryFromSliceError::__description unstable<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use cmp::Ordering;
use convert::TryFrom;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

/// The error type returned when a conversion from a slice to an array fails.
#[unstable(feature = "try_from", issue = "33417")]
#[derive(Debug, Copy, Clone)]
pub struct TryFromSliceError(());

impl fmt::Display for TryFromSliceError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.__description())
    }
}

impl TryFromSliceError {
    #[unstable(feature = "array_error_internals",
           reason = "available through Error trait and this method should not \
                     be exposed publicly",
           issue = "0")]
    #[inline]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        "could not convert slice to array"
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[unstable(feature = "try_from", issue = "33417")]
            impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_ptr() as *const [T; $N];
                        unsafe { Ok(&*ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[unstable(feature = "try_from", issue = "33417")]
            impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_mut_ptr() as *mut [T; $N];
                        unsafe { Ok(&mut *ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<|endoftext|>


<commit_before>/*!
The kind traits

Rust types can be classified in vairous useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

The 4 kinds are

* Copy - types that may be copied without allocation. This includes
  scalar types and managed pointers, and exludes owned pointers. It
  also excludes types that implement `Drop`.

* Send - owned types and types containing owned types.  These types
  may be transferred across task boundaries.

* Const - types that are deeply immutable. Const types are used for
  freezable data structures.

* Owned - types that do not contain borrowed pointers. Note that this
  meaning of 'owned' conflicts with 'owned pointers'. The two notions
  of ownership are different.

`Copy` types include both implicitly copyable types that the compiler
will copy automatically and non-implicitly copyable types that require
the `copy` keyword to copy. Types that do not implement `Copy` may
instead implement `Clone`.

*/

#[lang="copy"]
pub trait Copy {
    // Empty.
}

#[lang="send"]
pub trait Send {
    // Empty.
}

#[lang="const"]
pub trait Const {
    // Empty.
}

#[lang="owned"]
pub trait Owned {
    // Empty.
}
<commit_msg>Fix small typo in kinds documentation<commit_after>/*!
The kind traits

Rust types can be classified in various useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

The 4 kinds are

* Copy - types that may be copied without allocation. This includes
  scalar types and managed pointers, and exludes owned pointers. It
  also excludes types that implement `Drop`.

* Send - owned types and types containing owned types.  These types
  may be transferred across task boundaries.

* Const - types that are deeply immutable. Const types are used for
  freezable data structures.

* Owned - types that do not contain borrowed pointers. Note that this
  meaning of 'owned' conflicts with 'owned pointers'. The two notions
  of ownership are different.

`Copy` types include both implicitly copyable types that the compiler
will copy automatically and non-implicitly copyable types that require
the `copy` keyword to copy. Types that do not implement `Copy` may
instead implement `Clone`.

*/

#[lang="copy"]
pub trait Copy {
    // Empty.
}

#[lang="send"]
pub trait Send {
    // Empty.
}

#[lang="const"]
pub trait Const {
    // Empty.
}

#[lang="owned"]
pub trait Owned {
    // Empty.
}
<|endoftext|>


<commit_before>use std::os::raw::c_int;
use std::mem;

use common::{BfResult, Error, Count};
use rts;
use state::DEFAULT_CAPACITY;
use peephole;

use super::wrapper::*;

/// Program forms that can be compiled and run via LLVM.
pub trait LlvmCompilable {
    /// Compile the given program into the peephole AST to prepare for LLVM compilation.
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R;

    /// JIT compile and run the given program via LLVM.
    fn llvm_run(&self, memory_size: Option<usize>) -> BfResult<()> {
        self.with_peephole(|ast| compile_and_run(ast, memory_size, false))
    }
}

/// State required for the LLVM compiler.
struct Compiler<'a> {
    /// The LLVM context
    context:        &'a Context,
    /// The main module
    module:         Module<'a>,
    /// A builder positioned at the current end of the program
    builder:        Builder<'a>,
    /// Label to jump to for pointer underflow
    underflow:      BasicBlock<'a>,
    /// Label to jump to for pointer overflow
    overflow:       BasicBlock<'a>,
    /// The native C `int` type, for `putchar` and `getchar`
    int_type:       Type<'a>,
    /// The size of memory, for bounds checks
    memory_size:    Value<'a>,
    /// The main function
    main_function:  Value<'a>,
    /// `getchar`
    read_function:  Value<'a>,
    /// `putchar`
    write_function: Value<'a>,
    /// The program’s memory (“tape”)
    memory:         Value<'a>,
    /// The current offset into memory
    pointer:        Value<'a>,
}

/// JIT compile and run the given program via LLVM.
pub fn compile_and_run(program: &peephole::Program, memory_size: Option<usize>, debug: bool)
                       -> BfResult<()> {
    let context = Context::new();

    let compiler = Compiler::prologue(&context, memory_size.unwrap_or(DEFAULT_CAPACITY) as u64);
    compiler.compile_block(program);
    compiler.epilogue();

    compiler.module.optimize(3, 0);

    if debug {
        compiler.module.dump();
        compiler.module.verify().unwrap();
    }

    // This panics if LLVM fails.
    let result = compiler.module.run_function(compiler.main_function).unwrap();

    match result {
        rts::OKAY       => Ok(()),
        rts::UNDERFLOW  => Err(Error::PointerUnderflow),
        rts::OVERFLOW   => Err(Error::PointerOverflow),
        _ => panic!("unrecognized error code"),
    }
}

impl<'a> Compiler<'a> {
    fn compile_block(&self, body: &[peephole::Statement]) {
        use peephole::Statement::*;
        use common::Instruction::*;

        let builder = self.builder;

        for statement in body {
            match *statement {
                Instr(Right(count)) => {
                    let new_pointer = self.load_pos_offset(count, "new_pointer");
                    builder.store(new_pointer, self.pointer);
                }

                Instr(Left(count)) => {
                    let new_pointer = self.load_neg_offset(count, "new_pointer");
                    builder.store(new_pointer, self.pointer);
                }

                Instr(Add(count)) => {
                    let count = Value::get_u8(&self.context, count);
                    let old_value = self.load_data("old_val");
                    let new_value = builder.add(old_value, count, "new_val");
                    self.store_data(new_value);
                }

                Instr(In) => {
                    let result = builder.call(self.read_function, &[], "");
                    let result = builder.trunc(result, Type::get_i8(self.context), "");
                    self.store_data(result);
                }

                Instr(Out) => {
                    let argument = self.load_data("data");
                    let argument = builder.zext(argument, self.int_type, "");
                    builder.call(self.write_function, &[argument], "");
                }

                Instr(SetZero) => {
                    self.store_data(Value::get_u8(self.context, 0));
                }

                Instr(FindZeroRight(count)) => {
                    let instr = Loop(vec![Instr(Right(count))].into_boxed_slice());
                    self.compile_block(&[instr]);
                }

                Instr(FindZeroLeft(count)) => {
                    let instr = Loop(vec![Instr(Left(count))].into_boxed_slice());
                    self.compile_block(&[instr]);
                }

                Instr(OffsetAddRight(count)) => {
                    let do_it = self.main_function.append("do_it");
                    let after = self.main_function.append("after");

                    self.if_not0(do_it, after);

                    builder.position_at_end(do_it);
                    let pointer = self.load_pos_offset(count, "offset_ptr");
                    let to_add = self.load_data("to_add");
                    self.store_data(Value::get_u8(&self.context, 0));
                    let add_to = self.load_data_at(pointer, "add_to");
                    let sum = builder.add(to_add, add_to, "sum");
                    self.store_data_at(pointer, sum);
                    builder.br(after);

                    builder.position_at_end(after);
                }

                Instr(OffsetAddLeft(count)) => {
                    let do_it = self.main_function.append("do_it");
                    let after = self.main_function.append("after");

                    self.if_not0(do_it, after);

                    builder.position_at_end(do_it);
                    let pointer = self.load_neg_offset(count, "offset_ptr");
                    let to_add = self.load_data("to_add");
                    self.store_data(Value::get_u8(&self.context, 0));
                    let add_to = self.load_data_at(pointer, "add_to");
                    let sum = builder.add(to_add, add_to, "sum");
                    self.store_data_at(pointer, sum);
                    builder.br(after);

                    builder.position_at_end(after);
                }

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected instruction"),

                Loop(ref body) => {
                    let header = self.main_function.append("loop_header");
                    let true_  = self.main_function.append("loop_body");
                    let false_ = self.main_function.append("after_loop");

                    builder.br(header);

                    builder.position_at_end(header);
                    self.if_not0(true_, false_);

                    builder.position_at_end(true_);
                    self.compile_block(body);
                    builder.br(header);

                    builder.position_at_end(false_);
                }
            }
        }
    }

    /// Set up compilation.
    fn prologue(context: &'a Context, memory_size: u64) -> Self {
        let module = Module::new(&context, "bfi_module");

        // Some useful types
        let i64_type        = Type::get_i64(&context);
        let i32_type        = Type::get_i32(&context);
        let i8_type         = Type::get_i8(&context);
        let bool_type       = Type::get_bool(&context);
        let void_type       = Type::get_void(&context);
        let char_ptr_type   = Type::get_pointer(i8_type);

        // getchar and putchar use C's int type, which varies in size.
        let int_type = if mem::size_of::<c_int>() == 4 {i32_type} else {i64_type};

        // The size of memory as an LLVM Value
        let memory_size = Value::get_u64(&context, memory_size);

        // Create the main function, create an entry basic block, and position a builder at entry.
        let main_function_type = Type::get_function(&[], i64_type);
        let main_function  = module.add_function("bfi_main", main_function_type);
        let entry_bb = main_function.append("entry");
        let builder = Builder::new(&context);
        builder.position_at_end(entry_bb);

        // All state for the compiler.
        let compiler = Compiler {
            context:        context,
            module:         module,
            builder:        builder,
            underflow:      main_function.append("underflow"),
            overflow:       main_function.append("overflow"),
            int_type:       int_type,
            memory_size:    memory_size,
            main_function:  main_function,
            pointer:        builder.alloca(i64_type, "pointer"),
            memory:         builder.array_alloca(i8_type, memory_size, "memory"),
            read_function: {
                let read_function_type = Type::get_function(&[], int_type);
                module.add_function("getchar", read_function_type)
            },
            write_function: {
                let write_function_type = Type::get_function(&[int_type], int_type);
                module.add_function("putchar", write_function_type)
            }
        };

        // Zero-initialize the memory
        let memset_type = Type::get_function(&[char_ptr_type, i8_type, i64_type, i32_type, bool_type],
                                             void_type);
        let memset = compiler.module.add_function("llvm.memset.p0i8.i64", memset_type);
        builder.call(memset,
                     &[compiler.memory,
                         Value::get_u8(&context, 0),
                         compiler.memory_size,
                         Value::get_u32(&context, 0),
                         Value::get_bool(&context, false)],
                     "");

        // Start the data pointer at 0.
        builder.store(Value::get_u64(&context, 0), compiler.pointer);

        compiler
    }

    /// Emit the returns for the successful path and both error paths.
    fn epilogue(&self) {
        self.builder.ret(Value::get_u64(&self.context, rts::OKAY));

        self.builder.position_at_end(self.underflow);
        self.builder.ret(Value::get_u64(&self.context, rts::UNDERFLOW));

        self.builder.position_at_end(self.overflow);
        self.builder.ret(Value::get_u64(&self.context, rts::OVERFLOW));
    }

    /// Branch based on whether the byte at the data pointer is 0.
    fn if_not0(&self, true_: BasicBlock<'a>, false_: BasicBlock<'a>) {
        let byte = self.load_data("data");
        let zero = Value::get_u8(self.context, 0);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntNE, byte, zero, "comparison");
        self.builder.cond_br(comparison, true_, false_);
    }

    /// Load the byte from the given index into memory.
    fn load_data_at(&self, index: Value<'a>, name: &str) -> Value<'a> {
        let address = self.builder.gep(self.memory, &[index], "data_ptr");
        self.builder.load(address, name)
    }

    /// Store the given value at the given index into memory.
    fn store_data_at(&self, index: Value<'a>, value: Value<'a>) {
        let address = self.builder.gep(self.memory, &[index], "data_ptr");
        self.builder.store(value, address);
    }

    /// Load the byte from the data pointer.
    fn load_data(&self, name: &str) -> Value<'a> {
        let pointer = self.builder.load(self.pointer, "");
        self.load_data_at(pointer, name)
    }

    /// Store the given value at the data pointer.
    fn store_data(&self, value: Value<'a>) {
        let pointer = self.builder.load(self.pointer, "");
        self.store_data_at(pointer, value);
    }

    /// Add the given offset to the data pointer, checking for overflow.
    fn load_pos_offset(&self, offset: Count, name: &str) -> Value<'a> {
        let success = self.main_function.append("right_success");
        let old_pointer = self.builder.load(self.pointer, "old_pointer");
        let allowed = self.builder.sub(self.memory_size, old_pointer, "room");
        let offset = Value::get_u64(&self.context, offset as u64);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntULT, offset, allowed, "allowed");
        self.builder.cond_br(comparison, success, self.overflow);
        self.builder.position_at_end(success);
        self.builder.add(old_pointer, offset, name)
    }

    /// Subtract the given offset from the data pointer, checking for underflow.
    fn load_neg_offset(&self, offset: Count, name: &str) -> Value<'a> {
        let success = self.main_function.append("left_success");
        let old_pointer = self.builder.load(self.pointer, "old_pointer");
        let offset = Value::get_u64(&self.context, offset as u64);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntULE, offset, old_pointer,
                                     "allowed");
        self.builder.cond_br(comparison, success, self.underflow);
        self.builder.position_at_end(success);
        self.builder.sub(old_pointer, offset, name)
    }
}

impl LlvmCompilable for peephole::Program {
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R
    {
        k(self)
    }
}

impl<T: peephole::PeepholeCompilable + ?Sized> LlvmCompilable for T {
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R
    {
        k(&self.peephole_compile())
    }
}
<commit_msg>Clippy clean: removed needless borrows.<commit_after>use std::os::raw::c_int;
use std::mem;

use common::{BfResult, Error, Count};
use rts;
use state::DEFAULT_CAPACITY;
use peephole;

use super::wrapper::*;

/// Program forms that can be compiled and run via LLVM.
pub trait LlvmCompilable {
    /// Compile the given program into the peephole AST to prepare for LLVM compilation.
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R;

    /// JIT compile and run the given program via LLVM.
    fn llvm_run(&self, memory_size: Option<usize>) -> BfResult<()> {
        self.with_peephole(|ast| compile_and_run(ast, memory_size, false))
    }
}

/// State required for the LLVM compiler.
struct Compiler<'a> {
    /// The LLVM context
    context:        &'a Context,
    /// The main module
    module:         Module<'a>,
    /// A builder positioned at the current end of the program
    builder:        Builder<'a>,
    /// Label to jump to for pointer underflow
    underflow:      BasicBlock<'a>,
    /// Label to jump to for pointer overflow
    overflow:       BasicBlock<'a>,
    /// The native C `int` type, for `putchar` and `getchar`
    int_type:       Type<'a>,
    /// The size of memory, for bounds checks
    memory_size:    Value<'a>,
    /// The main function
    main_function:  Value<'a>,
    /// `getchar`
    read_function:  Value<'a>,
    /// `putchar`
    write_function: Value<'a>,
    /// The program’s memory (“tape”)
    memory:         Value<'a>,
    /// The current offset into memory
    pointer:        Value<'a>,
}

/// JIT compile and run the given program via LLVM.
pub fn compile_and_run(program: &peephole::Program, memory_size: Option<usize>, debug: bool)
                       -> BfResult<()> {
    let context = Context::new();

    let compiler = Compiler::prologue(&context, memory_size.unwrap_or(DEFAULT_CAPACITY) as u64);
    compiler.compile_block(program);
    compiler.epilogue();

    compiler.module.optimize(3, 0);

    if debug {
        compiler.module.dump();
        compiler.module.verify().unwrap();
    }

    // This panics if LLVM fails.
    let result = compiler.module.run_function(compiler.main_function).unwrap();

    match result {
        rts::OKAY       => Ok(()),
        rts::UNDERFLOW  => Err(Error::PointerUnderflow),
        rts::OVERFLOW   => Err(Error::PointerOverflow),
        _ => panic!("unrecognized error code"),
    }
}

impl<'a> Compiler<'a> {
    fn compile_block(&self, body: &[peephole::Statement]) {
        use peephole::Statement::*;
        use common::Instruction::*;

        let builder = self.builder;

        for statement in body {
            match *statement {
                Instr(Right(count)) => {
                    let new_pointer = self.load_pos_offset(count, "new_pointer");
                    builder.store(new_pointer, self.pointer);
                }

                Instr(Left(count)) => {
                    let new_pointer = self.load_neg_offset(count, "new_pointer");
                    builder.store(new_pointer, self.pointer);
                }

                Instr(Add(count)) => {
                    let count = Value::get_u8(self.context, count);
                    let old_value = self.load_data("old_val");
                    let new_value = builder.add(old_value, count, "new_val");
                    self.store_data(new_value);
                }

                Instr(In) => {
                    let result = builder.call(self.read_function, &[], "");
                    let result = builder.trunc(result, Type::get_i8(self.context), "");
                    self.store_data(result);
                }

                Instr(Out) => {
                    let argument = self.load_data("data");
                    let argument = builder.zext(argument, self.int_type, "");
                    builder.call(self.write_function, &[argument], "");
                }

                Instr(SetZero) => {
                    self.store_data(Value::get_u8(self.context, 0));
                }

                Instr(FindZeroRight(count)) => {
                    let instr = Loop(vec![Instr(Right(count))].into_boxed_slice());
                    self.compile_block(&[instr]);
                }

                Instr(FindZeroLeft(count)) => {
                    let instr = Loop(vec![Instr(Left(count))].into_boxed_slice());
                    self.compile_block(&[instr]);
                }

                Instr(OffsetAddRight(count)) => {
                    let do_it = self.main_function.append("do_it");
                    let after = self.main_function.append("after");

                    self.if_not0(do_it, after);

                    builder.position_at_end(do_it);
                    let pointer = self.load_pos_offset(count, "offset_ptr");
                    let to_add = self.load_data("to_add");
                    self.store_data(Value::get_u8(self.context, 0));
                    let add_to = self.load_data_at(pointer, "add_to");
                    let sum = builder.add(to_add, add_to, "sum");
                    self.store_data_at(pointer, sum);
                    builder.br(after);

                    builder.position_at_end(after);
                }

                Instr(OffsetAddLeft(count)) => {
                    let do_it = self.main_function.append("do_it");
                    let after = self.main_function.append("after");

                    self.if_not0(do_it, after);

                    builder.position_at_end(do_it);
                    let pointer = self.load_neg_offset(count, "offset_ptr");
                    let to_add = self.load_data("to_add");
                    self.store_data(Value::get_u8(self.context, 0));
                    let add_to = self.load_data_at(pointer, "add_to");
                    let sum = builder.add(to_add, add_to, "sum");
                    self.store_data_at(pointer, sum);
                    builder.br(after);

                    builder.position_at_end(after);
                }

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected instruction"),

                Loop(ref body) => {
                    let header = self.main_function.append("loop_header");
                    let true_  = self.main_function.append("loop_body");
                    let false_ = self.main_function.append("after_loop");

                    builder.br(header);

                    builder.position_at_end(header);
                    self.if_not0(true_, false_);

                    builder.position_at_end(true_);
                    self.compile_block(body);
                    builder.br(header);

                    builder.position_at_end(false_);
                }
            }
        }
    }

    /// Set up compilation.
    fn prologue(context: &'a Context, memory_size: u64) -> Self {
        let module = Module::new(context, "bfi_module");

        // Some useful types
        let i64_type        = Type::get_i64(context);
        let i32_type        = Type::get_i32(context);
        let i8_type         = Type::get_i8(context);
        let bool_type       = Type::get_bool(context);
        let void_type       = Type::get_void(context);
        let char_ptr_type   = Type::get_pointer(i8_type);

        // getchar and putchar use C's int type, which varies in size.
        let int_type = if mem::size_of::<c_int>() == 4 {i32_type} else {i64_type};

        // The size of memory as an LLVM Value
        let memory_size = Value::get_u64(context, memory_size);

        // Create the main function, create an entry basic block, and position a builder at entry.
        let main_function_type = Type::get_function(&[], i64_type);
        let main_function  = module.add_function("bfi_main", main_function_type);
        let entry_bb = main_function.append("entry");
        let builder = Builder::new(context);
        builder.position_at_end(entry_bb);

        // All state for the compiler.
        let compiler = Compiler {
            context:        context,
            module:         module,
            builder:        builder,
            underflow:      main_function.append("underflow"),
            overflow:       main_function.append("overflow"),
            int_type:       int_type,
            memory_size:    memory_size,
            main_function:  main_function,
            pointer:        builder.alloca(i64_type, "pointer"),
            memory:         builder.array_alloca(i8_type, memory_size, "memory"),
            read_function: {
                let read_function_type = Type::get_function(&[], int_type);
                module.add_function("getchar", read_function_type)
            },
            write_function: {
                let write_function_type = Type::get_function(&[int_type], int_type);
                module.add_function("putchar", write_function_type)
            }
        };

        // Zero-initialize the memory
        let memset_type = Type::get_function(&[char_ptr_type, i8_type, i64_type, i32_type, bool_type],
                                             void_type);
        let memset = compiler.module.add_function("llvm.memset.p0i8.i64", memset_type);
        builder.call(memset,
                     &[compiler.memory,
                         Value::get_u8(context, 0),
                         compiler.memory_size,
                         Value::get_u32(context, 0),
                         Value::get_bool(context, false)],
                     "");

        // Start the data pointer at 0.
        builder.store(Value::get_u64(context, 0), compiler.pointer);

        compiler
    }

    /// Emit the returns for the successful path and both error paths.
    fn epilogue(&self) {
        self.builder.ret(Value::get_u64(self.context, rts::OKAY));

        self.builder.position_at_end(self.underflow);
        self.builder.ret(Value::get_u64(self.context, rts::UNDERFLOW));

        self.builder.position_at_end(self.overflow);
        self.builder.ret(Value::get_u64(self.context, rts::OVERFLOW));
    }

    /// Branch based on whether the byte at the data pointer is 0.
    fn if_not0(&self, true_: BasicBlock<'a>, false_: BasicBlock<'a>) {
        let byte = self.load_data("data");
        let zero = Value::get_u8(self.context, 0);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntNE, byte, zero, "comparison");
        self.builder.cond_br(comparison, true_, false_);
    }

    /// Load the byte from the given index into memory.
    fn load_data_at(&self, index: Value<'a>, name: &str) -> Value<'a> {
        let address = self.builder.gep(self.memory, &[index], "data_ptr");
        self.builder.load(address, name)
    }

    /// Store the given value at the given index into memory.
    fn store_data_at(&self, index: Value<'a>, value: Value<'a>) {
        let address = self.builder.gep(self.memory, &[index], "data_ptr");
        self.builder.store(value, address);
    }

    /// Load the byte from the data pointer.
    fn load_data(&self, name: &str) -> Value<'a> {
        let pointer = self.builder.load(self.pointer, "");
        self.load_data_at(pointer, name)
    }

    /// Store the given value at the data pointer.
    fn store_data(&self, value: Value<'a>) {
        let pointer = self.builder.load(self.pointer, "");
        self.store_data_at(pointer, value);
    }

    /// Add the given offset to the data pointer, checking for overflow.
    fn load_pos_offset(&self, offset: Count, name: &str) -> Value<'a> {
        let success = self.main_function.append("right_success");
        let old_pointer = self.builder.load(self.pointer, "old_pointer");
        let allowed = self.builder.sub(self.memory_size, old_pointer, "room");
        let offset = Value::get_u64(self.context, offset as u64);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntULT, offset, allowed, "allowed");
        self.builder.cond_br(comparison, success, self.overflow);
        self.builder.position_at_end(success);
        self.builder.add(old_pointer, offset, name)
    }

    /// Subtract the given offset from the data pointer, checking for underflow.
    fn load_neg_offset(&self, offset: Count, name: &str) -> Value<'a> {
        let success = self.main_function.append("left_success");
        let old_pointer = self.builder.load(self.pointer, "old_pointer");
        let offset = Value::get_u64(self.context, offset as u64);
        let comparison = self.builder.cmp(LLVMIntPredicate::LLVMIntULE, offset, old_pointer,
                                     "allowed");
        self.builder.cond_br(comparison, success, self.underflow);
        self.builder.position_at_end(success);
        self.builder.sub(old_pointer, offset, name)
    }
}

impl LlvmCompilable for peephole::Program {
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R
    {
        k(self)
    }
}

impl<T: peephole::PeepholeCompilable + ?Sized> LlvmCompilable for T {
    fn with_peephole<F, R>(&self, k: F) -> R
        where F: FnOnce(&peephole::Program) -> R
    {
        k(&self.peephole_compile())
    }
}
<|endoftext|>


<commit_before>extern crate crowbook;
use crowbook::cleaner::Cleaner;
use crowbook::cleaner::French;
use std::borrow::Cow;

// Code to end shell colouring
pub const SHELL_COLOUR_OFF: &'static str = "\x1B[0m";
pub const SHELL_COLOUR_RED: &'static str = "\x1B[1m\x1B[31m";
pub const SHELL_COLOUR_BLUE: &'static str = "\x1B[1m\x1B[36m";
pub const SHELL_COLOUR_ORANGE: &'static str = "\x1B[1m\x1B[33m";
pub const SHELL_COLOUR_GREEN: &'static str = "\x1B[1m\x1B[32m";

fn display_spaces(s: &str) {
    let mut res = String::with_capacity(s.len());
    let nb_char = ' ';
    let nb_char_narrow = '\u{202F}'; // narrow non breaking space
    let nb_char_em = '\u{2002}'; // demi em space

    for c in s.chars() {
        if c == nb_char {
            res.push_str(&format!("{}{}{}",
                                  SHELL_COLOUR_ORANGE,
                                  '_',
                                  SHELL_COLOUR_OFF));
        } else if c == nb_char_narrow {
            res.push_str(&format!("{}{}{}",
                                  SHELL_COLOUR_BLUE,
                                  '_',
                                  SHELL_COLOUR_OFF));
        } else if c == nb_char_em {
            res.push_str(&format!("{}{}{}",
                                  SHELL_COLOUR_RED,
                                  '_',
                                  SHELL_COLOUR_OFF));
        } else {
            res.push(c);
        }
    }
    println!("{}\n\n", res);
}

fn main() {
    let s = Cow::Borrowed("10 000 €");
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed("10 000 EUR");
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed("10 000 EUROS");
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed("10 000 fr");
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed("tiret cadratin en début : espace insécable non justifiante, pour que les dialogues restent alignés");
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed(r#"– tiret non cadratin en début : question délicate, est-ce l'ouverture
d'un dialogue ? une liste ? cela dit ce n'est pas a priori l'usage
normal d'un tiret non cadratin suivi d'espace, qui est..."#);
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed(r#"l'angoisse : l'incise. J'ai bien aimé ce film — pas vous ? Là, il semblerait logique de mettre une espace insécable après le tiret. Mais il faut en mettre une avant lorsque ça se referme — comme ça —, sauf
qu'on ne peut pas juste compter les tirets parce que des fois une
incise n'est pas refermée par un tiret — comme en fin de phrase. Le
problème c'est qu'il est dur de trouver des règles simples — repérer
un point n'est pas suffisant, M. le petit malin ! — et qu'au final
avoir une règle qui marche à cent pour cent nécessiterait de l'analyse
syntaxique assez poussée – ce qui va au-delà des prétentions de mon logiciel.."#);
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed(r#"« en début : on pourrait aussi avoir une espace insécable non justifiante, mais de fait l'alignement sera de toute façon rompu car
suivi en général par tiret cadratin. Il faut juste éviter l'espace
fine, qui colle un peu trop le guillemet au dialogue..."#);
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed(r#"— par contre », objecta-t-elle, « il serait bien que si le premier guillemet fermant apparaît sans ouvrant, on en conclut qu'il s'agissait d'un dialogue »"#);
    display_spaces(French.clean(s, false).as_ref());

    let s = Cow::Borrowed(r#"Un « guillemet » pas en début : là, par contre, l'espace insécable fine est bien,
parce que c'est pas terrible d'avoir de grand espaces quand « on » met
un mot entre guillemets"#);
    display_spaces(French.clean(s, false).as_ref());
}
<commit_msg>Remove test_cleaner example<commit_after><|endoftext|>


<commit_before>pub fn reply(message: &str) -> &str {
    unimplemented!()
}
<commit_msg>bob: eliminate stub warnings<commit_after>pub fn reply(message: &str) -> &str {
    unimplemented!("have Bob reply to the incoming message: {}", message)
}
<|endoftext|>