<commit_before>use rustc::ty::{Ty, layout::TyLayout};
use rustc::mir;

use crate::*;

pub trait EvalContextExt<'tcx> {
    fn ptr_op(
        &self,
        bin_op: mir::BinOp,
        left: Scalar<Borrow>,
        left_layout: TyLayout<'tcx>,
        right: Scalar<Borrow>,
        right_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)>;

    fn ptr_int_arithmetic(
        &self,
        bin_op: mir::BinOp,
        left: Pointer<Borrow>,
        right: u128,
        signed: bool,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)>;

    fn ptr_eq(
        &self,
        left: Scalar<Borrow>,
        right: Scalar<Borrow>,
        size: Size,
    ) -> EvalResult<'tcx, bool>;

    fn pointer_offset_inbounds(
        &self,
        ptr: Scalar<Borrow>,
        pointee_ty: Ty<'tcx>,
        offset: i64,
    ) -> EvalResult<'tcx, Scalar<Borrow>>;
}

impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, 'tcx> {
    fn ptr_op(
        &self,
        bin_op: mir::BinOp,
        left: Scalar<Borrow>,
        left_layout: TyLayout<'tcx>,
        right: Scalar<Borrow>,
        right_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
        use rustc::mir::BinOp::*;

        trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
        debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);

        match bin_op {
            Offset => {
                let pointee_ty = left_layout.ty
                    .builtin_deref(true)
                    .expect("Offset called on non-ptr type")
                    .ty;
                let ptr = self.pointer_offset_inbounds(
                    left,
                    pointee_ty,
                    right.to_isize(self)?,
                )?;
                Ok((ptr, false))
            }
            // These work on anything
            Eq =>
                Ok((Scalar::from_bool(self.ptr_eq(left, right, left_layout.size)?), false)),
            Ne =>
                Ok((Scalar::from_bool(!self.ptr_eq(left, right, left_layout.size)?), false)),
            // These need both to be pointer, and fail if they are not in the same location
            Lt | Le | Gt | Ge | Sub if left.is_ptr() && right.is_ptr() => {
                let left = left.to_ptr().expect("we checked is_ptr");
                let right = right.to_ptr().expect("we checked is_ptr");
                if left.alloc_id == right.alloc_id {
                    let res = match bin_op {
                        Lt => left.offset < right.offset,
                        Le => left.offset <= right.offset,
                        Gt => left.offset > right.offset,
                        Ge => left.offset >= right.offset,
                        Sub => {
                            // subtract the offsets
                            let left_offset = Scalar::from_uint(left.offset.bytes(), self.memory().pointer_size());
                            let right_offset = Scalar::from_uint(right.offset.bytes(), self.memory().pointer_size());
                            let layout = self.layout_of(self.tcx.types.usize)?;
                            return self.binary_op(
                                Sub,
                                left_offset, layout,
                                right_offset, layout,
                            )
                        }
                        _ => bug!("We already established it has to be one of these operators."),
                    };
                    Ok((Scalar::from_bool(res), false))
                } else {
                    // Both are pointers, but from different allocations.
                    err!(InvalidPointerMath)
                }
            }
            // These work if the left operand is a pointer, and the right an integer
            Add | BitAnd | Sub | Rem if left.is_ptr() && right.is_bits() => {
                // Cast to i128 is fine as we checked the kind to be ptr-sized
                self.ptr_int_arithmetic(
                    bin_op,
                    left.to_ptr().expect("we checked is_ptr"),
                    right.to_bits(self.memory().pointer_size()).expect("we checked is_bits"),
                    right_layout.abi.is_signed(),
                )
            }
            // Commutative operators also work if the integer is on the left
            Add | BitAnd if left.is_bits() && right.is_ptr() => {
                // This is a commutative operation, just swap the operands
                self.ptr_int_arithmetic(
                    bin_op,
                    right.to_ptr().expect("we checked is_ptr"),
                    left.to_bits(self.memory().pointer_size()).expect("we checked is_bits"),
                    left_layout.abi.is_signed(),
                )
            }
            // Nothing else works
            _ => err!(InvalidPointerMath),
        }
    }

    fn ptr_eq(
        &self,
        left: Scalar<Borrow>,
        right: Scalar<Borrow>,
        size: Size,
    ) -> EvalResult<'tcx, bool> {
        Ok(match (left, right) {
            (Scalar::Bits { .. }, Scalar::Bits { .. }) =>
                left.to_bits(size)? == right.to_bits(size)?,
            (Scalar::Ptr(left), Scalar::Ptr(right)) => {
                // Comparison illegal if one of them is out-of-bounds, *unless* they
                // are in the same allocation.
                if left.alloc_id == right.alloc_id {
                    left.offset == right.offset
                } else {
                    // This accepts one-past-the end.  So technically there is still
                    // some non-determinism that we do not fully rule out when two
                    // allocations sit right next to each other.  The C/C++ standards are
                    // somewhat fuzzy about this case, so I think for now this check is
                    // "good enough".
                    // Dead allocations in miri cannot overlap with live allocations, but
                    // on read hardware this can easily happen. Thus for comparisons we require
                    // both pointers to be live.
                    self.memory().check_bounds_ptr(left, InboundsCheck::Live)?;
                    self.memory().check_bounds_ptr(right, InboundsCheck::Live)?;
                    // Two in-bounds pointers, we can compare across allocations
                    left == right
                }
            }
            // Comparing ptr and integer
            (Scalar::Ptr(ptr), Scalar::Bits { bits, size }) |
            (Scalar::Bits { bits, size }, Scalar::Ptr(ptr)) => {
                assert_eq!(size as u64, self.pointer_size().bytes());
                let bits = bits as u64;

                // Case I: Comparing with NULL
                if bits == 0 {
                    // Test if the ptr is in-bounds. Then it cannot be NULL.
                    // Even dangling pointers cannot be NULL.
                    if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
                        return Ok(false);
                    }
                }

                let (alloc_size, alloc_align) = self.memory()
                    .get_size_and_align(ptr.alloc_id, InboundsCheck::MaybeDead)
                    .expect("determining size+align of dead ptr cannot fail");

                // Case II: Alignment gives it away
                if ptr.offset.bytes() % alloc_align.bytes() == 0 {
                    // The offset maintains the allocation alignment, so we know `base+offset`
                    // is aligned by `alloc_align`.
                    // FIXME: We could be even more general, e.g. offset 2 into a 4-aligned
                    // allocation cannot equal 3.
                    if bits % alloc_align.bytes() != 0 {
                        // The integer is *not* aligned. So they cannot be equal.
                        return Ok(false);
                    }
                }
                // Case III: The integer is too big, and the allocation goes on a bit
                // without wrapping around the address space.
                {
                    // Compute the highest address at which this allocation could live.
                    // Substract one more, because it must be possible to add the size
                    // to the base address without overflowing -- IOW, the very last address
                    // of the address space is never dereferencable (but it can be in-bounds, i.e.,
                    // one-past-the-end).
                    let max_base_addr =
                        ((1u128 << self.pointer_size().bits())
                         - u128::from(alloc_size.bytes())
                         - 1
                        ) as u64;
                    if let Some(max_addr) = max_base_addr.checked_add(ptr.offset.bytes()) {
                        if bits > max_addr {
                            // The integer is too big, this cannot possibly be equal
                            return Ok(false)
                        }
                    }
                }

                // None of the supported cases.
                return err!(InvalidPointerMath);
            }
        })
    }

    fn ptr_int_arithmetic(
        &self,
        bin_op: mir::BinOp,
        left: Pointer<Borrow>,
        right: u128,
        signed: bool,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
        use rustc::mir::BinOp::*;

        fn map_to_primval((res, over): (Pointer<Borrow>, bool)) -> (Scalar<Borrow>, bool) {
            (Scalar::Ptr(res), over)
        }

        Ok(match bin_op {
            Sub =>
                // The only way this can overflow is by underflowing, so signdeness of the right operands does not matter
                map_to_primval(left.overflowing_signed_offset(-(right as i128), self)),
            Add if signed =>
                map_to_primval(left.overflowing_signed_offset(right as i128, self)),
            Add if !signed =>
                map_to_primval(left.overflowing_offset(Size::from_bytes(right as u64), self)),

            BitAnd if !signed => {
                let ptr_base_align = self.memory().get(left.alloc_id)?.align.bytes();
                let base_mask = {
                    // FIXME: Use interpret::truncate, once that takes a Size instead of a Layout
                    let shift = 128 - self.memory().pointer_size().bits();
                    let value = !(ptr_base_align as u128 - 1);
                    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
                    (value << shift) >> shift
                };
                let ptr_size = self.memory().pointer_size().bytes() as u8;
                trace!("Ptr BitAnd, align {}, operand {:#010x}, base_mask {:#010x}",
                    ptr_base_align, right, base_mask);
                if right & base_mask == base_mask {
                    // Case 1: The base address bits are all preserved, i.e., right is all-1 there
                    let offset = (left.offset.bytes() as u128 & right) as u64;
                    (
                        Scalar::Ptr(Pointer::new_with_tag(
                            left.alloc_id,
                            Size::from_bytes(offset),
                            left.tag,
                        )),
                        false,
                    )
                } else if right & base_mask == 0 {
                    // Case 2: The base address bits are all taken away, i.e., right is all-0 there
                    (Scalar::Bits { bits: (left.offset.bytes() as u128) & right, size: ptr_size }, false)
                } else {
                    return err!(ReadPointerAsBytes);
                }
            }

            Rem if !signed => {
                // Doing modulo a divisor of the alignment is allowed.
                // (Intuition: Modulo a divisor leaks less information.)
                let ptr_base_align = self.memory().get(left.alloc_id)?.align.bytes();
                let right = right as u64;
                let ptr_size = self.memory().pointer_size().bytes() as u8;
                if right == 1 {
                    // modulo 1 is always 0
                    (Scalar::Bits { bits: 0, size: ptr_size }, false)
                } else if ptr_base_align % right == 0 {
                    // the base address would be cancelled out by the modulo operation, so we can
                    // just take the modulo of the offset
                    (Scalar::Bits { bits: (left.offset.bytes() % right) as u128, size: ptr_size }, false)
                } else {
                    return err!(ReadPointerAsBytes);
                }
            }

            _ => {
                let msg = format!("unimplemented binary op on pointer {:?}: {:?}, {:?} ({})", bin_op, left, right, if signed { "signed" } else { "unsigned" });
                return err!(Unimplemented(msg));
            }
        })
    }

    /// This function raises an error if the offset moves the pointer outside of its allocation.  We consider
    /// ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0).
    /// We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own
    /// allocation.
    fn pointer_offset_inbounds(
        &self,
        ptr: Scalar<Borrow>,
        pointee_ty: Ty<'tcx>,
        offset: i64,
    ) -> EvalResult<'tcx, Scalar<Borrow>> {
        // FIXME: assuming here that type size is < i64::max_value()
        let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
        let offset = offset.checked_mul(pointee_size).ok_or_else(|| EvalErrorKind::Overflow(mir::BinOp::Mul))?;
        // Now let's see what kind of pointer this is
        if let Scalar::Ptr(ptr) = ptr {
            // Both old and new pointer must be in-bounds of a *live* allocation.
            // (Of the same allocation, but that part is trivial with our representation.)
            let alloc = self.memory().get(ptr.alloc_id)?;
            alloc.check_bounds_ptr(ptr)?;
            let ptr = ptr.signed_offset(offset, self)?;
            alloc.check_bounds_ptr(ptr)?;
            Ok(Scalar::Ptr(ptr))
        } else {
            // An integer pointer. They can only be offset by 0, and we pretend there
            // is a little zero-sized allocation here.
            if offset == 0 {
                Ok(ptr)
            } else {
                err!(InvalidPointerMath)
            }
        }
    }
}
<commit_msg>use memory::check_bounds_ptr for offset check<commit_after>use rustc::ty::{Ty, layout::TyLayout};
use rustc::mir;

use crate::*;

pub trait EvalContextExt<'tcx> {
    fn ptr_op(
        &self,
        bin_op: mir::BinOp,
        left: Scalar<Borrow>,
        left_layout: TyLayout<'tcx>,
        right: Scalar<Borrow>,
        right_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)>;

    fn ptr_int_arithmetic(
        &self,
        bin_op: mir::BinOp,
        left: Pointer<Borrow>,
        right: u128,
        signed: bool,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)>;

    fn ptr_eq(
        &self,
        left: Scalar<Borrow>,
        right: Scalar<Borrow>,
        size: Size,
    ) -> EvalResult<'tcx, bool>;

    fn pointer_offset_inbounds(
        &self,
        ptr: Scalar<Borrow>,
        pointee_ty: Ty<'tcx>,
        offset: i64,
    ) -> EvalResult<'tcx, Scalar<Borrow>>;
}

impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, 'tcx> {
    fn ptr_op(
        &self,
        bin_op: mir::BinOp,
        left: Scalar<Borrow>,
        left_layout: TyLayout<'tcx>,
        right: Scalar<Borrow>,
        right_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
        use rustc::mir::BinOp::*;

        trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
        debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);

        match bin_op {
            Offset => {
                let pointee_ty = left_layout.ty
                    .builtin_deref(true)
                    .expect("Offset called on non-ptr type")
                    .ty;
                let ptr = self.pointer_offset_inbounds(
                    left,
                    pointee_ty,
                    right.to_isize(self)?,
                )?;
                Ok((ptr, false))
            }
            // These work on anything
            Eq =>
                Ok((Scalar::from_bool(self.ptr_eq(left, right, left_layout.size)?), false)),
            Ne =>
                Ok((Scalar::from_bool(!self.ptr_eq(left, right, left_layout.size)?), false)),
            // These need both to be pointer, and fail if they are not in the same location
            Lt | Le | Gt | Ge | Sub if left.is_ptr() && right.is_ptr() => {
                let left = left.to_ptr().expect("we checked is_ptr");
                let right = right.to_ptr().expect("we checked is_ptr");
                if left.alloc_id == right.alloc_id {
                    let res = match bin_op {
                        Lt => left.offset < right.offset,
                        Le => left.offset <= right.offset,
                        Gt => left.offset > right.offset,
                        Ge => left.offset >= right.offset,
                        Sub => {
                            // subtract the offsets
                            let left_offset = Scalar::from_uint(left.offset.bytes(), self.memory().pointer_size());
                            let right_offset = Scalar::from_uint(right.offset.bytes(), self.memory().pointer_size());
                            let layout = self.layout_of(self.tcx.types.usize)?;
                            return self.binary_op(
                                Sub,
                                left_offset, layout,
                                right_offset, layout,
                            )
                        }
                        _ => bug!("We already established it has to be one of these operators."),
                    };
                    Ok((Scalar::from_bool(res), false))
                } else {
                    // Both are pointers, but from different allocations.
                    err!(InvalidPointerMath)
                }
            }
            // These work if the left operand is a pointer, and the right an integer
            Add | BitAnd | Sub | Rem if left.is_ptr() && right.is_bits() => {
                // Cast to i128 is fine as we checked the kind to be ptr-sized
                self.ptr_int_arithmetic(
                    bin_op,
                    left.to_ptr().expect("we checked is_ptr"),
                    right.to_bits(self.memory().pointer_size()).expect("we checked is_bits"),
                    right_layout.abi.is_signed(),
                )
            }
            // Commutative operators also work if the integer is on the left
            Add | BitAnd if left.is_bits() && right.is_ptr() => {
                // This is a commutative operation, just swap the operands
                self.ptr_int_arithmetic(
                    bin_op,
                    right.to_ptr().expect("we checked is_ptr"),
                    left.to_bits(self.memory().pointer_size()).expect("we checked is_bits"),
                    left_layout.abi.is_signed(),
                )
            }
            // Nothing else works
            _ => err!(InvalidPointerMath),
        }
    }

    fn ptr_eq(
        &self,
        left: Scalar<Borrow>,
        right: Scalar<Borrow>,
        size: Size,
    ) -> EvalResult<'tcx, bool> {
        Ok(match (left, right) {
            (Scalar::Bits { .. }, Scalar::Bits { .. }) =>
                left.to_bits(size)? == right.to_bits(size)?,
            (Scalar::Ptr(left), Scalar::Ptr(right)) => {
                // Comparison illegal if one of them is out-of-bounds, *unless* they
                // are in the same allocation.
                if left.alloc_id == right.alloc_id {
                    left.offset == right.offset
                } else {
                    // This accepts one-past-the end.  So technically there is still
                    // some non-determinism that we do not fully rule out when two
                    // allocations sit right next to each other.  The C/C++ standards are
                    // somewhat fuzzy about this case, so I think for now this check is
                    // "good enough".
                    // Dead allocations in miri cannot overlap with live allocations, but
                    // on read hardware this can easily happen. Thus for comparisons we require
                    // both pointers to be live.
                    self.memory().check_bounds_ptr(left, InboundsCheck::Live)?;
                    self.memory().check_bounds_ptr(right, InboundsCheck::Live)?;
                    // Two in-bounds pointers, we can compare across allocations
                    left == right
                }
            }
            // Comparing ptr and integer
            (Scalar::Ptr(ptr), Scalar::Bits { bits, size }) |
            (Scalar::Bits { bits, size }, Scalar::Ptr(ptr)) => {
                assert_eq!(size as u64, self.pointer_size().bytes());
                let bits = bits as u64;

                // Case I: Comparing with NULL
                if bits == 0 {
                    // Test if the ptr is in-bounds. Then it cannot be NULL.
                    // Even dangling pointers cannot be NULL.
                    if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
                        return Ok(false);
                    }
                }

                let (alloc_size, alloc_align) = self.memory()
                    .get_size_and_align(ptr.alloc_id, InboundsCheck::MaybeDead)
                    .expect("determining size+align of dead ptr cannot fail");

                // Case II: Alignment gives it away
                if ptr.offset.bytes() % alloc_align.bytes() == 0 {
                    // The offset maintains the allocation alignment, so we know `base+offset`
                    // is aligned by `alloc_align`.
                    // FIXME: We could be even more general, e.g. offset 2 into a 4-aligned
                    // allocation cannot equal 3.
                    if bits % alloc_align.bytes() != 0 {
                        // The integer is *not* aligned. So they cannot be equal.
                        return Ok(false);
                    }
                }
                // Case III: The integer is too big, and the allocation goes on a bit
                // without wrapping around the address space.
                {
                    // Compute the highest address at which this allocation could live.
                    // Substract one more, because it must be possible to add the size
                    // to the base address without overflowing -- IOW, the very last address
                    // of the address space is never dereferencable (but it can be in-bounds, i.e.,
                    // one-past-the-end).
                    let max_base_addr =
                        ((1u128 << self.pointer_size().bits())
                         - u128::from(alloc_size.bytes())
                         - 1
                        ) as u64;
                    if let Some(max_addr) = max_base_addr.checked_add(ptr.offset.bytes()) {
                        if bits > max_addr {
                            // The integer is too big, this cannot possibly be equal
                            return Ok(false)
                        }
                    }
                }

                // None of the supported cases.
                return err!(InvalidPointerMath);
            }
        })
    }

    fn ptr_int_arithmetic(
        &self,
        bin_op: mir::BinOp,
        left: Pointer<Borrow>,
        right: u128,
        signed: bool,
    ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
        use rustc::mir::BinOp::*;

        fn map_to_primval((res, over): (Pointer<Borrow>, bool)) -> (Scalar<Borrow>, bool) {
            (Scalar::Ptr(res), over)
        }

        Ok(match bin_op {
            Sub =>
                // The only way this can overflow is by underflowing, so signdeness of the right operands does not matter
                map_to_primval(left.overflowing_signed_offset(-(right as i128), self)),
            Add if signed =>
                map_to_primval(left.overflowing_signed_offset(right as i128, self)),
            Add if !signed =>
                map_to_primval(left.overflowing_offset(Size::from_bytes(right as u64), self)),

            BitAnd if !signed => {
                let ptr_base_align = self.memory().get(left.alloc_id)?.align.bytes();
                let base_mask = {
                    // FIXME: Use interpret::truncate, once that takes a Size instead of a Layout
                    let shift = 128 - self.memory().pointer_size().bits();
                    let value = !(ptr_base_align as u128 - 1);
                    // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
                    (value << shift) >> shift
                };
                let ptr_size = self.memory().pointer_size().bytes() as u8;
                trace!("Ptr BitAnd, align {}, operand {:#010x}, base_mask {:#010x}",
                    ptr_base_align, right, base_mask);
                if right & base_mask == base_mask {
                    // Case 1: The base address bits are all preserved, i.e., right is all-1 there
                    let offset = (left.offset.bytes() as u128 & right) as u64;
                    (
                        Scalar::Ptr(Pointer::new_with_tag(
                            left.alloc_id,
                            Size::from_bytes(offset),
                            left.tag,
                        )),
                        false,
                    )
                } else if right & base_mask == 0 {
                    // Case 2: The base address bits are all taken away, i.e., right is all-0 there
                    (Scalar::Bits { bits: (left.offset.bytes() as u128) & right, size: ptr_size }, false)
                } else {
                    return err!(ReadPointerAsBytes);
                }
            }

            Rem if !signed => {
                // Doing modulo a divisor of the alignment is allowed.
                // (Intuition: Modulo a divisor leaks less information.)
                let ptr_base_align = self.memory().get(left.alloc_id)?.align.bytes();
                let right = right as u64;
                let ptr_size = self.memory().pointer_size().bytes() as u8;
                if right == 1 {
                    // modulo 1 is always 0
                    (Scalar::Bits { bits: 0, size: ptr_size }, false)
                } else if ptr_base_align % right == 0 {
                    // the base address would be cancelled out by the modulo operation, so we can
                    // just take the modulo of the offset
                    (Scalar::Bits { bits: (left.offset.bytes() % right) as u128, size: ptr_size }, false)
                } else {
                    return err!(ReadPointerAsBytes);
                }
            }

            _ => {
                let msg = format!("unimplemented binary op on pointer {:?}: {:?}, {:?} ({})", bin_op, left, right, if signed { "signed" } else { "unsigned" });
                return err!(Unimplemented(msg));
            }
        })
    }

    /// This function raises an error if the offset moves the pointer outside of its allocation.  We consider
    /// ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0).
    /// We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own
    /// allocation.
    fn pointer_offset_inbounds(
        &self,
        ptr: Scalar<Borrow>,
        pointee_ty: Ty<'tcx>,
        offset: i64,
    ) -> EvalResult<'tcx, Scalar<Borrow>> {
        // FIXME: assuming here that type size is < i64::max_value()
        let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
        let offset = offset.checked_mul(pointee_size).ok_or_else(|| EvalErrorKind::Overflow(mir::BinOp::Mul))?;
        // Now let's see what kind of pointer this is
        if let Scalar::Ptr(ptr) = ptr {
            // Both old and new pointer must be in-bounds of a *live* allocation.
            // (Of the same allocation, but that part is trivial with our representation.)
            self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
            let ptr = ptr.signed_offset(offset, self)?;
            self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
            Ok(Scalar::Ptr(ptr))
        } else {
            // An integer pointer. They can only be offset by 0, and we pretend there
            // is a little zero-sized allocation here.
            if offset == 0 {
                Ok(ptr)
            } else {
                err!(InvalidPointerMath)
            }
        }
    }
}
<|endoftext|>


<commit_before>include!("header.rs");

#[test]
fn solve_upper() {
    let r_dist = RealNormal::new(0.0, 1.0);
    let a = drop_lower(Array::<f64, _>::random((3, 3), r_dist));
    println!("a = \n{:?}", &a);
    let b = Array::<f64, _>::random(3, r_dist);
    println!("b = \n{:?}", &b);
    let x = a.solve_upper(b.clone()).unwrap();
    println!("x = \n{:?}", &x);
    println!("Ax = \n{:?}", a.dot(&x));
    all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
}

#[test]
fn solve_upper_t() {
    let r_dist = RealNormal::new(0., 1.);
    let a = drop_lower(Array::<f64, _>::random((3, 3), r_dist).reversed_axes());
    println!("a = \n{:?}", &a);
    let b = Array::<f64, _>::random(3, r_dist);
    println!("b = \n{:?}", &b);
    let x = a.solve_upper(b.clone()).unwrap();
    println!("x = \n{:?}", &x);
    println!("Ax = \n{:?}", a.dot(&x));
    all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
}

#[test]
fn solve_lower() {
    let r_dist = RealNormal::new(0., 1.);
    let a = drop_upper(Array::<f64, _>::random((3, 3), r_dist));
    println!("a = \n{:?}", &a);
    let b = Array::<f64, _>::random(3, r_dist);
    println!("b = \n{:?}", &b);
    let x = a.solve_lower(b.clone()).unwrap();
    println!("x = \n{:?}", &x);
    println!("Ax = \n{:?}", a.dot(&x));
    all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
}

#[test]
fn solve_lower_t() {
    let r_dist = RealNormal::new(0., 1.);
    let a = drop_upper(Array::<f64, _>::random((3, 3), r_dist).reversed_axes());
    println!("a = \n{:?}", &a);
    let b = Array::<f64, _>::random(3, r_dist);
    println!("b = \n{:?}", &b);
    let x = a.solve_lower(b.clone()).unwrap();
    println!("x = \n{:?}", &x);
    println!("Ax = \n{:?}", a.dot(&x));
    all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
}
<commit_msg>Test for triangular<commit_after>include!("header.rs");

macro_rules! impl_test {
    ($modname:ident, $random:path) => {
mod $modname {
    use ndarray::prelude::*;
    use ndarray_linalg::prelude::*;
    use ndarray_numtest::prelude::*;
    use ndarray_rand::RandomExt;
    #[test]
    fn solve_upper() {
        let r_dist = RealNormal::new(0.0, 1.0);
        let a = drop_lower($random((3, 3), r_dist));
        println!("a = \n{:?}", &a);
        let b = $random(3, r_dist);
        println!("b = \n{:?}", &b);
        let x = a.solve_upper(b.clone()).unwrap();
        println!("x = \n{:?}", &x);
        println!("Ax = \n{:?}", a.dot(&x));
        all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
    }

    #[test]
    fn solve_upper_t() {
        let r_dist = RealNormal::new(0., 1.);
        let a = drop_lower($random((3, 3), r_dist).reversed_axes());
        println!("a = \n{:?}", &a);
        let b = $random(3, r_dist);
        println!("b = \n{:?}", &b);
        let x = a.solve_upper(b.clone()).unwrap();
        println!("x = \n{:?}", &x);
        println!("Ax = \n{:?}", a.dot(&x));
        all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
    }

    #[test]
    fn solve_lower() {
        let r_dist = RealNormal::new(0., 1.);
        let a = drop_upper($random((3, 3), r_dist));
        println!("a = \n{:?}", &a);
        let b = $random(3, r_dist);
        println!("b = \n{:?}", &b);
        let x = a.solve_lower(b.clone()).unwrap();
        println!("x = \n{:?}", &x);
        println!("Ax = \n{:?}", a.dot(&x));
        all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
    }

    #[test]
    fn solve_lower_t() {
        let r_dist = RealNormal::new(0., 1.);
        let a = drop_upper($random((3, 3), r_dist).reversed_axes());
        println!("a = \n{:?}", &a);
        let b = $random(3, r_dist);
        println!("b = \n{:?}", &b);
        let x = a.solve_lower(b.clone()).unwrap();
        println!("x = \n{:?}", &x);
        println!("Ax = \n{:?}", a.dot(&x));
        all_close_l2(&a.dot(&x), &b, 1e-7).unwrap();
    }
}
}} // impl_test_opnorm

impl_test!(owned, Array<f64, _>::random);
impl_test!(shared, RcArray<f64, _>::random);
<|endoftext|>


<commit_before>use std::thread::Thread;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};

use iron::prelude::*;
use iron::{status, headers};
use iron::Handler;
use iron::modifier::Modifier;
use router::{Router, Params};
use serde::{Serialize, Serializer};
use serde_json;

use super::breakpoint_map::BreakpointMap;
use super::cpu_snapshot::CpuSnapshot;
use memory::Memory;

pub struct ToggleBreakpointResponse {
    addr: u16,
    is_set: bool,
}

impl ToggleBreakpointResponse {
    pub fn new(addr: u16, is_set: bool) -> Self {
        ToggleBreakpointResponse {
            addr: addr,
            is_set: is_set,
        }
    }
}

impl Serialize for ToggleBreakpointResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("ToggleBreakpointResponse", 2));
        try!(serializer.serialize_struct_elt(&mut state, "address", self.addr));
        try!(serializer.serialize_struct_elt(&mut state, "isSet", self.is_set));
        serializer.serialize_struct_end(state)
    }
}

pub struct GetSnapshotHandler<M: Memory> {
    snapshot: Arc<Mutex<CpuSnapshot<M>>>,
}

impl<M: Memory> GetSnapshotHandler<M> {
    pub fn new(snapshot: Arc<Mutex<CpuSnapshot<M>>>) -> Self {
        GetSnapshotHandler { snapshot: snapshot }
    }
}

impl<M: Memory> Handler for GetSnapshotHandler<M> {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        let snapshot = &(*self.snapshot.lock().unwrap());
        let json = serde_json::to_string(snapshot).unwrap();
        let resp = response_with((status::Ok, json));
        Ok(resp)
    }
}

pub struct ToggleBreakpointHandler {
    breakpoints: Arc<Mutex<BreakpointMap>>,
}

impl ToggleBreakpointHandler {
    pub fn new(breakpoints: Arc<Mutex<BreakpointMap>>) -> Self {
        ToggleBreakpointHandler { breakpoints: breakpoints }
    }
}

impl Handler for ToggleBreakpointHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        if let Some(addr) = get_router(req).find("addr").and_then(|a| a.parse::<u16>().ok()) {
            let mut breakpoints = &mut (*self.breakpoints.lock().unwrap());
            let is_set = breakpoints.toggle(addr);
            println!("Http thread received set breakpoint command!");
            let resp_model = ToggleBreakpointResponse::new(addr, is_set);
            let resp_body = serde_json::to_string(&resp_model).unwrap();
            let resp = response_with((status::Ok, resp_body));
            Ok(resp)
        } else {
            let resp = response_with((status::BadRequest));
            Ok(resp)
        }
    }
}

struct ContinueResponse {
    continued: bool,
}

impl Serialize for ContinueResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("ContinueResponse", 1));
        try!(serializer.serialize_struct_elt(&mut state, "continued", self.continued));
        serializer.serialize_struct_end(state)
    }
}

pub struct StepResponse {
    stepped: bool,
}

impl Serialize for StepResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("StepResponse", 1));
        try!(serializer.serialize_struct_elt(&mut state, "stepped", self.stepped));
        serializer.serialize_struct_end(state)
    }
}

pub struct StepHandler {
    cpu_thread_handle: Thread,
}

impl StepHandler {
    pub fn new(cpu_thread: Thread) -> Self {
        StepHandler { cpu_thread_handle: cpu_thread }
    }
}

impl Handler for StepHandler {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        self.cpu_thread_handle.unpark();
        let resp = StepResponse { stepped: true };
        let json = serde_json::to_string(&resp).unwrap();
        Ok(response_with((status::Ok, json)))
    }
}

pub struct ContinueHandler {
    cpu_thread_handle: Thread,
    is_stepping: Arc<AtomicBool>,
}

impl ContinueHandler {
    pub fn new(cpu_thread: Thread, is_stepping: Arc<AtomicBool>) -> Self {
        ContinueHandler {
            cpu_thread_handle: cpu_thread,
            is_stepping: is_stepping,
        }
    }
}

impl Handler for ContinueHandler {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        self.is_stepping.compare_and_swap(true, false, Ordering::Relaxed);
        self.cpu_thread_handle.unpark();
        let resp = ContinueResponse { continued: true };
        let json = serde_json::to_string(&resp).unwrap();
        Ok(response_with((status::Ok, json)))
    }
}

fn get_router<'a>(req: &'a Request) -> &'a Params {
    req.extensions.get::<Router>().unwrap()
}

fn response_with<M: Modifier<Response>>(m: M) -> Response {
    let mut resp = Response::with(m);
    resp.headers.set(headers::AccessControlAllowOrigin::Any);
    resp.headers.set(headers::ContentType::json());
    resp
}
<commit_msg>Better logging<commit_after>use std::thread::Thread;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};

use iron::prelude::*;
use iron::{status, headers};
use iron::Handler;
use iron::modifier::Modifier;
use router::{Router, Params};
use serde::{Serialize, Serializer};
use serde_json;

use super::breakpoint_map::BreakpointMap;
use super::cpu_snapshot::CpuSnapshot;
use memory::Memory;

pub struct ToggleBreakpointResponse {
    addr: u16,
    is_set: bool,
}

impl ToggleBreakpointResponse {
    pub fn new(addr: u16, is_set: bool) -> Self {
        ToggleBreakpointResponse {
            addr: addr,
            is_set: is_set,
        }
    }
}

impl Serialize for ToggleBreakpointResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("ToggleBreakpointResponse", 2));
        try!(serializer.serialize_struct_elt(&mut state, "address", self.addr));
        try!(serializer.serialize_struct_elt(&mut state, "isSet", self.is_set));
        serializer.serialize_struct_end(state)
    }
}

pub struct GetSnapshotHandler<M: Memory> {
    snapshot: Arc<Mutex<CpuSnapshot<M>>>,
}

impl<M: Memory> GetSnapshotHandler<M> {
    pub fn new(snapshot: Arc<Mutex<CpuSnapshot<M>>>) -> Self {
        GetSnapshotHandler { snapshot: snapshot }
    }
}

impl<M: Memory> Handler for GetSnapshotHandler<M> {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        let snapshot = &(*self.snapshot.lock().unwrap());
        let json = serde_json::to_string(snapshot).unwrap();
        let resp = response_with((status::Ok, json));
        Ok(resp)
    }
}

pub struct ToggleBreakpointHandler {
    breakpoints: Arc<Mutex<BreakpointMap>>,
}

impl ToggleBreakpointHandler {
    pub fn new(breakpoints: Arc<Mutex<BreakpointMap>>) -> Self {
        ToggleBreakpointHandler { breakpoints: breakpoints }
    }
}

impl Handler for ToggleBreakpointHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        info!("Toggle breakpoint request received!");
        if let Some(addr) = get_router(req).find("addr").and_then(|a| a.parse::<u16>().ok()) {
            let mut breakpoints = &mut (*self.breakpoints.lock().unwrap());
            let is_set = breakpoints.toggle(addr);
            let resp_model = ToggleBreakpointResponse::new(addr, is_set);
            let resp_body = serde_json::to_string(&resp_model).unwrap();
            let resp = response_with((status::Ok, resp_body));
            Ok(resp)
        } else {
            let resp = response_with((status::BadRequest));
            Ok(resp)
        }
    }
}

struct ContinueResponse {
    continued: bool,
}

impl Serialize for ContinueResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("ContinueResponse", 1));
        try!(serializer.serialize_struct_elt(&mut state, "continued", self.continued));
        serializer.serialize_struct_end(state)
    }
}

pub struct StepResponse {
    stepped: bool,
}

impl Serialize for StepResponse {
    fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
        let mut state = try!(serializer.serialize_struct("StepResponse", 1));
        try!(serializer.serialize_struct_elt(&mut state, "stepped", self.stepped));
        serializer.serialize_struct_end(state)
    }
}

pub struct StepHandler {
    cpu_thread_handle: Thread,
}

impl StepHandler {
    pub fn new(cpu_thread: Thread) -> Self {
        StepHandler { cpu_thread_handle: cpu_thread }
    }
}

impl Handler for StepHandler {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        info!("Step request received!");
        self.cpu_thread_handle.unpark();
        let resp = StepResponse { stepped: true };
        let json = serde_json::to_string(&resp).unwrap();
        Ok(response_with((status::Ok, json)))
    }
}

pub struct ContinueHandler {
    cpu_thread_handle: Thread,
    is_stepping: Arc<AtomicBool>,
}

impl ContinueHandler {
    pub fn new(cpu_thread: Thread, is_stepping: Arc<AtomicBool>) -> Self {
        ContinueHandler {
            cpu_thread_handle: cpu_thread,
            is_stepping: is_stepping,
        }
    }
}

impl Handler for ContinueHandler {
    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        info!("Continue request received!");
        self.is_stepping.compare_and_swap(true, false, Ordering::Relaxed);
        self.cpu_thread_handle.unpark();
        let resp = ContinueResponse { continued: true };
        let json = serde_json::to_string(&resp).unwrap();
        Ok(response_with((status::Ok, json)))
    }
}

fn get_router<'a>(req: &'a Request) -> &'a Params {
    req.extensions.get::<Router>().unwrap()
}

fn response_with<M: Modifier<Response>>(m: M) -> Response {
    let mut resp = Response::with(m);
    resp.headers.set(headers::AccessControlAllowOrigin::Any);
    resp.headers.set(headers::ContentType::json());
    resp
}
<|endoftext|>


<commit_before>// Copyright 2017 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.

use rustc::mir::Location;
use rustc::ty::RegionVid;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use std::fmt;
use syntax_pos::Span;
use std::ops::Deref;

#[derive(Clone, Default)]
crate struct ConstraintSet {
    constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
    seen_constraints: FxHashSet<(RegionVid, RegionVid)>,
}

impl ConstraintSet {
    pub fn push(&mut self, constraint: OutlivesConstraint) {
        debug!(
            "add_outlives({:?}: {:?} @ {:?}",
            constraint.sup, constraint.sub, constraint.point
        );
        if constraint.sup == constraint.sub {
            // 'a: 'a is pretty uninteresting
            return;
        }
        if self.seen_constraints.insert(constraint.dedup_key()) {
            self.constraints.push(constraint);
        }
    }

    /// Once all constraints have been added, `link()` is used to thread together the constraints
    /// based on which would be affected when a particular region changes. See the next field of
    /// `OutlivesContraint` for more details.
    /// link returns a map that is needed later by `each_affected_by_dirty`.
    pub fn link(&mut self, len: usize) -> IndexVec<RegionVid, Option<ConstraintIndex>> {
        let mut map = IndexVec::from_elem_n(None, len);

        for (idx, constraint) in self.constraints.iter_enumerated_mut().rev() {
            let mut head = &mut map[constraint.sub];
            debug_assert!(constraint.next.is_none());
            constraint.next = *head;
            *head = Some(idx);
        }

        map
    }

    /// When a region R1 changes, we need to reprocess all constraints R2: R1 to take into account
    /// any new elements that R1 now has. This method will quickly enumerate all such constraints
    /// (that is, constraints where R1 is in the "subregion" position).
    /// To use it, invoke with `map[R1]` where map is the map returned by `link`;
    /// the callback op will be invoked for each affected constraint.
    pub fn each_affected_by_dirty(
        &self,
        mut opt_dep_idx: Option<ConstraintIndex>,
        mut op: impl FnMut(ConstraintIndex),
    ) {
        while let Some(dep_idx) = opt_dep_idx {
            op(dep_idx);
            opt_dep_idx = self.constraints[dep_idx].next;
        }
    }
}

impl Deref for ConstraintSet {
    type Target = IndexVec<ConstraintIndex, OutlivesConstraint>;

    fn deref(&self) -> &Self::Target { &self.constraints }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OutlivesConstraint {
    // NB. The ordering here is not significant for correctness, but
    // it is for convenience. Before we dump the constraints in the
    // debugging logs, we sort them, and we'd like the "super region"
    // to be first, etc. (In particular, span should remain last.)
    /// The region SUP must outlive SUB...
    pub sup: RegionVid,

    /// Region that must be outlived.
    pub sub: RegionVid,

    /// At this location.
    pub point: Location,

    /// Later on, we thread the constraints onto a linked list
    /// grouped by their `sub` field. So if you had:
    ///
    /// Index | Constraint | Next Field
    /// ----- | ---------- | ----------
    /// 0     | `'a: 'b`   | Some(2)
    /// 1     | `'b: 'c`   | None
    /// 2     | `'c: 'b`   | None
    pub next: Option<ConstraintIndex>,

    /// Where did this constraint arise?
    pub span: Span,
}

impl OutlivesConstraint {
    pub fn dedup_key(&self) -> (RegionVid, RegionVid) {
        (self.sup, self.sub)
    }
}

impl fmt::Debug for OutlivesConstraint {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "({:?}: {:?} @ {:?}) due to {:?}",
            self.sup, self.sub, self.point, self.span
        )
    }
}

newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
<commit_msg>remove the FxHashSet since it's not helping us in practice<commit_after>// Copyright 2017 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.

use rustc::mir::Location;
use rustc::ty::RegionVid;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use std::fmt;
use syntax_pos::Span;
use std::ops::Deref;

#[derive(Clone, Default)]
crate struct ConstraintSet {
    constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
}

impl ConstraintSet {
    pub fn push(&mut self, constraint: OutlivesConstraint) {
        debug!(
            "add_outlives({:?}: {:?} @ {:?}",
            constraint.sup, constraint.sub, constraint.point
        );
        if constraint.sup == constraint.sub {
            // 'a: 'a is pretty uninteresting
            return;
        }
        self.constraints.push(constraint);
    }

    /// Once all constraints have been added, `link()` is used to thread together the constraints
    /// based on which would be affected when a particular region changes. See the next field of
    /// `OutlivesContraint` for more details.
    /// link returns a map that is needed later by `each_affected_by_dirty`.
    pub fn link(&mut self, len: usize) -> IndexVec<RegionVid, Option<ConstraintIndex>> {
        let mut map = IndexVec::from_elem_n(None, len);

        for (idx, constraint) in self.constraints.iter_enumerated_mut().rev() {
            let mut head = &mut map[constraint.sub];
            debug_assert!(constraint.next.is_none());
            constraint.next = *head;
            *head = Some(idx);
        }

        map
    }

    /// When a region R1 changes, we need to reprocess all constraints R2: R1 to take into account
    /// any new elements that R1 now has. This method will quickly enumerate all such constraints
    /// (that is, constraints where R1 is in the "subregion" position).
    /// To use it, invoke with `map[R1]` where map is the map returned by `link`;
    /// the callback op will be invoked for each affected constraint.
    pub fn each_affected_by_dirty(
        &self,
        mut opt_dep_idx: Option<ConstraintIndex>,
        mut op: impl FnMut(ConstraintIndex),
    ) {
        while let Some(dep_idx) = opt_dep_idx {
            op(dep_idx);
            opt_dep_idx = self.constraints[dep_idx].next;
        }
    }
}

impl Deref for ConstraintSet {
    type Target = IndexVec<ConstraintIndex, OutlivesConstraint>;

    fn deref(&self) -> &Self::Target { &self.constraints }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OutlivesConstraint {
    // NB. The ordering here is not significant for correctness, but
    // it is for convenience. Before we dump the constraints in the
    // debugging logs, we sort them, and we'd like the "super region"
    // to be first, etc. (In particular, span should remain last.)
    /// The region SUP must outlive SUB...
    pub sup: RegionVid,

    /// Region that must be outlived.
    pub sub: RegionVid,

    /// At this location.
    pub point: Location,

    /// Later on, we thread the constraints onto a linked list
    /// grouped by their `sub` field. So if you had:
    ///
    /// Index | Constraint | Next Field
    /// ----- | ---------- | ----------
    /// 0     | `'a: 'b`   | Some(2)
    /// 1     | `'b: 'c`   | None
    /// 2     | `'c: 'b`   | None
    pub next: Option<ConstraintIndex>,

    /// Where did this constraint arise?
    pub span: Span,
}

impl fmt::Debug for OutlivesConstraint {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(
            formatter,
            "({:?}: {:?} @ {:?}) due to {:?}",
            self.sup, self.sub, self.point, self.span
        )
    }
}

newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
<|endoftext|>


<commit_before>
/// Get the port from a string (ip)
pub fn parse_port(string: &str) -> &str {
    let mut a = 0;
    let mut b = 0;

    for (n, c) in string.chars().enumerate() {
        match c {
            '0' | '1' |
            '2' | '3' |
            '4' | '5' |
            '6' | '7' |
            '8' | '9' => b += 1,
            ':' => a = n + 1,
            _ => break,
        }
    }

    &string[a..b + 1]

}

/// Get the host from a string (ip)
pub fn parse_host(string: &str) -> &str {
    let mut b = 0;

    // TODO: Username/Password syntax
    for (n, c) in string.chars().enumerate() {
        match c {
            ':' | '/' => break,
            _ => b += 1,
        }
    }

    &string[..b + 1]

}
<commit_msg>Unpanickify any possible panics in `parse_host()`<commit_after>
/// Get the port from a string (ip)
pub fn parse_port(string: &str) -> &str {
    let mut a = 0;
    let mut b = 0;

    for (n, c) in string.chars().enumerate() {
        match c {
            '0' | '1' |
            '2' | '3' |
            '4' | '5' |
            '6' | '7' |
            '8' | '9' => b += 1,
            ':' => a = n + 1,
            _ => break,
        }
    }

    &string[a..b + 1]
}

/// Get the host from a string (ip)
pub fn parse_host(string: &str) -> &str {
    // TODO: Username/Password syntax
    let pos = match string.find(':') {
        Some(pos) => pos + 1,
        None => match string.find('/') {
            Some(pos) => pos + 1,
            None => string.len(),
        },
    };

    &string[..pos]
}
<|endoftext|>


<commit_before>/// Ye Olde Await Macro
///
/// Basically a translation of polling to yielding. This crate's macro is
/// reexported in the `futures_await` crate, you should not use this crate
/// specifically. If I knew how to define this macro in the `futures_await`
/// crate I would. Ideally this crate would not exist.

// TODO: how to define this in the `futures_await` crate but have it still
// importable via `futurses_await::prelude::await`?

#[macro_export]
macro_rules! await {
    ($e:expr) => ({
        let mut future = $e;
        loop {
            let poll = {
                let pin = unsafe {
                    ::futures::__rt::pin_api::PinMut::new_unchecked(&mut future)
                };
                ::futures::__rt::in_ctx(|ctx| ::futures::__rt::StableFuture::poll(pin, ctx))
            };
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }
            yield ::futures::__rt::Async::Pending
        }
    })
}

///
/// Await an item from the stream
/// Basically it does same as `await` macro, but for streams
///

#[macro_export]
macro_rules! await_item {
    ($e:expr) => ({
        loop {
            let poll = ::futures::__rt::in_ctx(|ctx| ::futures::Stream::poll_next(&mut $e, ctx));
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }

            yield ::futures::__rt::Async::Pending
        }
    })
}

// TODO: This macro needs to use an extra temporary variable because of
// rust-lang/rust#44197, once that's fixed this should just use $e directly
// inside the yield expression
#[macro_export]
macro_rules! stream_yield {
    ($e:expr) => ({
        let e = $e;
        yield ::futures::__rt::Async::Ready(e)
    })
}
<commit_msg>Suppress warning when used with the never_type feature<commit_after>/// Ye Olde Await Macro
///
/// Basically a translation of polling to yielding. This crate's macro is
/// reexported in the `futures_await` crate, you should not use this crate
/// specifically. If I knew how to define this macro in the `futures_await`
/// crate I would. Ideally this crate would not exist.

// TODO: how to define this in the `futures_await` crate but have it still
// importable via `futurses_await::prelude::await`?

#[macro_export]
macro_rules! await {
    ($e:expr) => ({
        let mut future = $e;
        loop {
            let poll = {
                let pin = unsafe {
                    ::futures::__rt::pin_api::PinMut::new_unchecked(&mut future)
                };
                ::futures::__rt::in_ctx(|ctx| ::futures::__rt::StableFuture::poll(pin, ctx))
            };
            // Allow for #[feature(never_type)] and Future<Error = !>
            #[allow(unreachable_code, unreachable_patterns)]
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }
            yield ::futures::__rt::Async::Pending
        }
    })
}

///
/// Await an item from the stream
/// Basically it does same as `await` macro, but for streams
///

#[macro_export]
macro_rules! await_item {
    ($e:expr) => ({
        loop {
            let poll = ::futures::__rt::in_ctx(|ctx| ::futures::Stream::poll_next(&mut $e, ctx));
            // Allow for #[feature(never_type)] and Stream<Error = !>
            #[allow(unreachable_code, unreachable_patterns)]
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }

            yield ::futures::__rt::Async::Pending
        }
    })
}

// TODO: This macro needs to use an extra temporary variable because of
// rust-lang/rust#44197, once that's fixed this should just use $e directly
// inside the yield expression
#[macro_export]
macro_rules! stream_yield {
    ($e:expr) => ({
        let e = $e;
        yield ::futures::__rt::Async::Ready(e)
    })
}
<|endoftext|>


<commit_before>#[crate_type = "rlib"];

use std::{char, iter};
use std::io::buffered::BufferedReader;
use std::io::File;

pub static EXPECTED_ANSWER: &'static str = "24702";

static BOARD_WIDTH: uint = 9;
static BOARD_HEIGHT: uint = 9;
static GROUP_WIDTH: uint = 3;
static GROUP_HEIGHT: uint = 3;
static MAX_NUMBER: uint = 9;
type BITS = u16;
static MASK_ALL: BITS = 0x1ff;

struct SuDoku {
    name: ~str,
    map: [[BITS, .. BOARD_WIDTH], .. BOARD_HEIGHT]
}

// #7622 (rust): #[deriving(TotalEq, Eq, Clone)] cannnot be used
impl TotalEq for SuDoku {
    #[inline]
    fn equals(&self, other: &SuDoku) -> bool {
        self.name == other.name && range(0, BOARD_HEIGHT).all(|y| self.map[y] == other.map[y])
    }
}

impl Eq for SuDoku {
    #[inline]
    fn eq(&self, other: &SuDoku) -> bool { self.equals(other) }
    #[inline]
    fn ne(&self, other: &SuDoku) -> bool { !self.equals(other) }
}

impl ToStr for SuDoku {
    fn to_str(&self) -> ~str {
        let rows = self.map.map(|row| {
            let cells = row.map(|&cell| {
                if cell.population_count() == 1 {
                    ~"_"
                } else {
                    (1u << cell.trailing_zeros()).to_str()
                }
            });
            cells.concat()
        });
        self.name + "\n" + rows.connect("\n")
    }
}

impl Clone for SuDoku {
    #[inline]
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

impl SuDoku {
    #[inline]
    fn get_num(&self, x: uint, y: uint) -> BITS {
        match self.map[y][x].population_count() {
            0 => -1,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }
}

fn read_sudoku<T: Reader>(r: &mut BufferedReader<T>) -> Option<SuDoku> {
    r.read_line()
        .and_then(|name| {
            let mut sudoku = SuDoku {
                name: name,
                map: [[MASK_ALL, .. BOARD_WIDTH], .. BOARD_HEIGHT]
            };
            for y in range(0, BOARD_HEIGHT) {
                match r.read_line() {
                    None => return None,
                    Some(line) => {
                        for x in range(0, BOARD_WIDTH) {
                            let n = char::to_digit(line[x] as char, 10).unwrap();
                            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
                        }
                    }
                }
            }
            Some(sudoku)
        })
}

fn solve_sudoku(mut puzzle: SuDoku) -> ~[SuDoku] {
    let group_it = range(0, GROUP_WIDTH * GROUP_HEIGHT)
        .map(|i| (i % GROUP_WIDTH, i / GROUP_WIDTH))
        .to_owned_vec();

    loop {
        let bkup = puzzle.clone();

        for y in range(0, BOARD_HEIGHT) {
            for x in range(0, BOARD_WIDTH) {
                if puzzle.map[y][x].population_count() != 1 { continue }

                let (x0, y0) = (x / GROUP_WIDTH * GROUP_WIDTH,
                                y / GROUP_HEIGHT * GROUP_HEIGHT);
                let row = range(0, BOARD_WIDTH).map(|x| (x, y));
                let col = range(0, BOARD_HEIGHT).map(|y| (x, y));
                let grp = group_it.iter().map(|&(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp)
                    .filter(|&pos: &(uint, uint)| pos != (x, y));
                let mask = !puzzle.map[y][x] & MASK_ALL;
                for (x, y) in it { puzzle.map[y][x] &= mask; }
            }
        }

        for n in range(0, MAX_NUMBER) {
            let bit = 1 << n;

            for y in range(0, BOARD_HEIGHT) {
                let mut it = range(0, BOARD_WIDTH)
                    .filter(|&x| puzzle.map[y][x] & bit != 0);
                let next = it.next();
                if next.is_none() || it.next().is_some() { continue }
                puzzle.map[y][next.unwrap()] = bit;
            }

            for x in range(0, BOARD_WIDTH) {
                let mut it = range(0, BOARD_HEIGHT)
                    .filter(|&y| puzzle.map[y][x] & bit != 0);
                let next = it.next();
                if next.is_none() || it.next().is_some() { continue }
                puzzle.map[next.unwrap()][x] = bit;
            }

            for y0 in iter::range_step(0, BOARD_HEIGHT, GROUP_WIDTH) {
                for x0 in iter::range_step(0, BOARD_WIDTH, GROUP_HEIGHT) {
                    let mut it = group_it
                        .iter()
                        .map(|&(dx, dy)| (x0 + dx, y0 + dy))
                        .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_some() && it.next().is_none() {
                        let (x, y) = next.unwrap();
                        puzzle.map[y][x] = bit;
                    }
                }
            }
        }

        if puzzle == bkup { break }
    }

    let it = range(0, BOARD_HEIGHT * BOARD_WIDTH)
        .map(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .map(|(x, y)| (x, y, puzzle.map[y][x].population_count()))
        .to_owned_vec();

    if it.iter().any(|&(_x, _y, cnt)| cnt == 0) { return ~[]; }
    if it.iter().all(|&(_x, _y, cnt)| cnt == 1) { return ~[puzzle]; }

    let (x, y, _cnt) = *it.iter()
        .filter(|& &(_x, _y, cnt)| cnt > 1)
        .min_by(|& &(_x, _y, cnt)| cnt)
        .unwrap();

    let mut answers = ~[];
    for n in range(0, MAX_NUMBER) {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { continue }

        let mut p2 = puzzle.clone();
        p2.map[y][x] = bit;
        answers.push_all(solve_sudoku(p2));
    }

    answers
}

pub fn solve() -> ~str {
    let mut br = BufferedReader::new(
        File::open(&Path::new("files/sudoku.txt")).expect("file not found."));

    let mut puzzles = ~[];
    loop {
        match read_sudoku(&mut br) {
            Some(sudoku) => puzzles.push(sudoku),
            None => break
        }
    }
    let mut answers = puzzles
        .move_iter()
        .map(solve_sudoku)
        .map(|ans| { assert_eq!(ans.len(), 1); ans[0] });
    let mut sum = 0;
    for ans in answers {
        sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
    }
    sum.to_str()
}
<commit_msg>Fix for compile<commit_after>#[crate_type = "rlib"];

use std::{char, iter};
use std::io::buffered::BufferedReader;
use std::io::File;
use std::num::Bitwise;

pub static EXPECTED_ANSWER: &'static str = "24702";

static BOARD_WIDTH: uint = 9;
static BOARD_HEIGHT: uint = 9;
static GROUP_WIDTH: uint = 3;
static GROUP_HEIGHT: uint = 3;
static MAX_NUMBER: uint = 9;
type BITS = u16;
static MASK_ALL: BITS = 0x1ff;

struct SuDoku {
    name: ~str,
    map: [[BITS, .. BOARD_WIDTH], .. BOARD_HEIGHT]
}

// #7622 (rust): #[deriving(TotalEq, Eq, Clone)] cannnot be used
impl TotalEq for SuDoku {
    #[inline]
    fn equals(&self, other: &SuDoku) -> bool {
        self.name == other.name && range(0, BOARD_HEIGHT).all(|y| self.map[y] == other.map[y])
    }
}

impl Eq for SuDoku {
    #[inline]
    fn eq(&self, other: &SuDoku) -> bool { self.equals(other) }
    #[inline]
    fn ne(&self, other: &SuDoku) -> bool { !self.equals(other) }
}

impl ToStr for SuDoku {
    fn to_str(&self) -> ~str {
        let rows = self.map.map(|row| {
            let cells = row.map(|&cell| {
                if cell.population_count() == 1 {
                    ~"_"
                } else {
                    (1u << cell.trailing_zeros()).to_str()
                }
            });
            cells.concat()
        });
        self.name + "\n" + rows.connect("\n")
    }
}

impl Clone for SuDoku {
    #[inline]
    fn clone(&self) -> SuDoku {
        SuDoku { name: self.name.clone(), map: self.map }
    }
}

impl SuDoku {
    #[inline]
    fn get_num(&self, x: uint, y: uint) -> BITS {
        match self.map[y][x].population_count() {
            0 => -1,
            1 => self.map[y][x].trailing_zeros() + 1,
            _ => 0
        }
    }
}

fn read_sudoku<T: Reader>(r: &mut BufferedReader<T>) -> Option<SuDoku> {
    r.read_line()
        .and_then(|name| {
            let mut sudoku = SuDoku {
                name: name,
                map: [[MASK_ALL, .. BOARD_WIDTH], .. BOARD_HEIGHT]
            };
            for y in range(0, BOARD_HEIGHT) {
                match r.read_line() {
                    None => return None,
                    Some(line) => {
                        for x in range(0, BOARD_WIDTH) {
                            let n = char::to_digit(line[x] as char, 10).unwrap();
                            if n != 0 { sudoku.map[y][x] = 1 << (n - 1); }
                        }
                    }
                }
            }
            Some(sudoku)
        })
}

fn solve_sudoku(mut puzzle: SuDoku) -> ~[SuDoku] {
    let group_it = range(0, GROUP_WIDTH * GROUP_HEIGHT)
        .map(|i| (i % GROUP_WIDTH, i / GROUP_WIDTH))
        .to_owned_vec();

    loop {
        let bkup = puzzle.clone();

        for y in range(0, BOARD_HEIGHT) {
            for x in range(0, BOARD_WIDTH) {
                if puzzle.map[y][x].population_count() != 1 { continue }

                let (x0, y0) = (x / GROUP_WIDTH * GROUP_WIDTH,
                                y / GROUP_HEIGHT * GROUP_HEIGHT);
                let row = range(0, BOARD_WIDTH).map(|x| (x, y));
                let col = range(0, BOARD_HEIGHT).map(|y| (x, y));
                let grp = group_it.iter().map(|&(dx, dy)| (x0 + dx, y0 + dy));

                let mut it = row.chain(col).chain(grp)
                    .filter(|&pos: &(uint, uint)| pos != (x, y));
                let mask = !puzzle.map[y][x] & MASK_ALL;
                for (x, y) in it { puzzle.map[y][x] &= mask; }
            }
        }

        for n in range(0, MAX_NUMBER) {
            let bit = 1 << n;

            for y in range(0, BOARD_HEIGHT) {
                let mut it = range(0, BOARD_WIDTH)
                    .filter(|&x| puzzle.map[y][x] & bit != 0);
                let next = it.next();
                if next.is_none() || it.next().is_some() { continue }
                puzzle.map[y][next.unwrap()] = bit;
            }

            for x in range(0, BOARD_WIDTH) {
                let mut it = range(0, BOARD_HEIGHT)
                    .filter(|&y| puzzle.map[y][x] & bit != 0);
                let next = it.next();
                if next.is_none() || it.next().is_some() { continue }
                puzzle.map[next.unwrap()][x] = bit;
            }

            for y0 in iter::range_step(0, BOARD_HEIGHT, GROUP_WIDTH) {
                for x0 in iter::range_step(0, BOARD_WIDTH, GROUP_HEIGHT) {
                    let mut it = group_it
                        .iter()
                        .map(|&(dx, dy)| (x0 + dx, y0 + dy))
                        .filter(|&(x, y)| puzzle.map[y][x] & bit != 0);
                    let next = it.next();
                    if next.is_some() && it.next().is_none() {
                        let (x, y) = next.unwrap();
                        puzzle.map[y][x] = bit;
                    }
                }
            }
        }

        if puzzle == bkup { break }
    }

    let it = range(0, BOARD_HEIGHT * BOARD_WIDTH)
        .map(|i| (i % BOARD_WIDTH, i / BOARD_WIDTH))
        .map(|(x, y)| (x, y, puzzle.map[y][x].population_count()))
        .to_owned_vec();

    if it.iter().any(|&(_x, _y, cnt)| cnt == 0) { return ~[]; }
    if it.iter().all(|&(_x, _y, cnt)| cnt == 1) { return ~[puzzle]; }

    let (x, y, _cnt) = *it.iter()
        .filter(|& &(_x, _y, cnt)| cnt > 1)
        .min_by(|& &(_x, _y, cnt)| cnt)
        .unwrap();

    let mut answers = ~[];
    for n in range(0, MAX_NUMBER) {
        let bit = 1 << n;
        if puzzle.map[y][x] & bit == 0 { continue }

        let mut p2 = puzzle.clone();
        p2.map[y][x] = bit;
        answers.push_all(solve_sudoku(p2));
    }

    answers
}

pub fn solve() -> ~str {
    let mut br = BufferedReader::new(
        File::open(&Path::new("files/sudoku.txt")).expect("file not found."));

    let mut puzzles = ~[];
    loop {
        match read_sudoku(&mut br) {
            Some(sudoku) => puzzles.push(sudoku),
            None => break
        }
    }
    let mut answers = puzzles
        .move_iter()
        .map(solve_sudoku)
        .map(|ans| { assert_eq!(ans.len(), 1); ans[0] });
    let mut sum = 0;
    for ans in answers {
        sum += 100 * ans.get_num(0, 0) + 10 * ans.get_num(1, 0) + ans.get_num(2, 0);
    }
    sum.to_str()
}
<|endoftext|>


<commit_before>use std::ffi::CString;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                      , BuilderRef
                  };
use seax::compiler_tools::ForkTable;

use position::Positional;

pub type IRResult = Result<ValueRef, Positional<String>>;
pub type SymbolTable<'a> = ForkTable<'a, &'a str, ValueRef>;

/// Trait for an object that can be compiled to LLVM IR
pub trait ToIR {
    fn to_ir(&self, context: LLVMContext) -> IRResult;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext<'a> {
    pub llctx: ContextRef,
    pub llmod: ModuleRef,
    pub llbuilder: BuilderRef,
    pub names: SymbolTable<'a>
}

// because we are in the Raw Pointer Sadness Zone (read: unsafe),
// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            panic!("assertion failed: {} returned null!", stringify!($target));
        } else { e }
    })
}

impl<'a> LLVMContext<'a> {

    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let ctx = not_null!(llvm::LLVMContextCreate());
            LLVMContext {
                llctx: ctx
              , llmod: not_null!(llvm::LLVMModuleCreateWithNameInContext(name.into_raw(), ctx))
              , llbuilder: not_null!(llvm::LLVMCreateBuilderInContext(ctx))
              , names: SymbolTable::new()
            }
        }
    }

    /// Dump the module's contents to stderr for debugging
    ///
    /// Apparently this is the only reasonable way to get a textual
    /// representation of a `ModuleRef` in `librustc_llvm`...
    pub fn dump(&self) {
        unsafe { llvm::LLVMDumpModule(self.llmod); }
    }
}

impl<'a> Drop for LLVMContext<'a> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMDisposeBuilder(self.llbuilder);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}
<commit_msg>Start on implementing Compile for things<commit_after>use std::ffi::CString;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                      , BuilderRef
                  };
use seax::compiler_tools::ForkTable;

use position::Positional;
use ast::Form;

pub type IRResult = Result<ValueRef, Positional<String>>;
pub type SymbolTable<'a> = ForkTable<'a, &'a str, ValueRef>;

/// Trait for that which may join in The Great Work
pub trait Compile {
    fn to_ir(&self, context: LLVMContext) -> IRResult;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext<'a> {
    pub llctx: ContextRef,
    pub llmod: ModuleRef,
    pub llbuilder: BuilderRef,
    pub names: SymbolTable<'a>
}

// because we are in the Raw Pointer Sadness Zone (read: unsafe),
// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            panic!("assertion failed: {} returned null!", stringify!($target));
        } else { e }
    })
}

impl<'a> LLVMContext<'a> {

    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let ctx = not_null!(llvm::LLVMContextCreate());
            LLVMContext {
                llctx: ctx
              , llmod: not_null!(llvm::LLVMModuleCreateWithNameInContext(name.into_raw(), ctx))
              , llbuilder: not_null!(llvm::LLVMCreateBuilderInContext(ctx))
              , names: SymbolTable::new()
            }
        }
    }

    /// Dump the module's contents to stderr for debugging
    ///
    /// Apparently this is the only reasonable way to get a textual
    /// representation of a `ModuleRef` in `librustc_llvm`...
    pub fn dump(&self) {
        unsafe { llvm::LLVMDumpModule(self.llmod); }
    }
}

impl<'a> Drop for LLVMContext<'a> {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMDisposeBuilder(self.llbuilder);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}

impl Compile for Form {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match self {
            &Form::Define(ref form) => form.compile(context)
        }
    }
}

impl Compile for DefForm {
    fn to_ir(&self, context: LLVMContext) -> IRResult {
        match *self {
            DefForm::TopLevel { ref name, ref annot, ref value } =>
                unimplemented!(),
            DefForm::Function { ref name, ref annot, ref formals, ref body } =>
                unimplemented!()
        }
    }
}
<|endoftext|>


<commit_before>//! Conversion

use super::models::{BufferObject, BufferResponse, XtensisObject};
<commit_msg>Remove unnecessary import<commit_after>//! Conversion
<|endoftext|>


<commit_before>use calx::{RngExt, hex_disc, HexGeom, hex_neighbors};
use euclid::{self, vec2};
use rand::{self, Rng};
use std::collections::HashSet;
use std::cmp::Ordering;

pub type Point2D = euclid::Point2D<i32>;
pub type Size2D = euclid::Size2D<i32>;

pub trait Dungeon {
    type Prefab: Prefab;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab;

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = Point2D>>(&mut self, area: I);

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = Point2D>>(&mut self, path: I);

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: Point2D);

    fn add_door(&mut self, pos: Point2D);

    fn add_up_stairs(&mut self, pos: Point2D);

    fn add_down_stairs(&mut self, pos: Point2D);
}

pub trait Prefab {
    fn contains(&self, pos: Point2D) -> bool;
    fn can_make_door(&self, pos: Point2D) -> bool;
    fn size(&self) -> Size2D;
}

pub struct DigCavesGen {
    domain: Vec<Point2D>,
}

impl DigCavesGen {
    pub fn new<I: IntoIterator<Item = Point2D>>(domain: I) -> DigCavesGen {
        DigCavesGen { domain: domain.into_iter().collect() }
    }

    pub fn dig<R: Rng, D, P>(&self, rng: &mut R, d: &mut D)
    where
        D: Dungeon<Prefab = P>,
        P: Prefab,
    {
        const INIT_P: f32 = 0.65;
        const N_ITERS: usize = 3;
        const WALL_THRESHOLD: u32 = 3;
        const MINIMAL_REGION_SIZE: usize = 8;

        // Initial cellular automata run, produces okay looking but usually not fully connected
        // cave map.
        let mut dug: HashSet<Point2D> = self.domain
            .iter()
            .filter(|_| rng.with_chance(INIT_P))
            .cloned()
            .collect();

        for _ in 0..N_ITERS {
            let mut dug2 = dug.clone();

            for &p in &self.domain {
                let n_walls: u32 = hex_disc(p, 1)
                    .filter(|&p2| p2 != p)
                    .map(|p2| !dug.contains(&p2) as u32)
                    .sum();
                let n_walls_2: u32 = hex_disc(p, 2)
                    .filter(|&p2| p2 != p)
                    .map(|p2| !dug.contains(&p2) as u32)
                    .sum();

                // Add a wall if there are either neighboring walls or if the cell is in the
                // centes of a large empty region.
                if n_walls >= WALL_THRESHOLD || n_walls_2 == 0 {
                    dug2.remove(&p);
                } else {
                    dug2.insert(p);
                }
            }

            dug = dug2;
        }

        // Connect separate regions
        let mut regions = separate_regions(dug.clone());
        // Remove uselessly small regions
        regions.retain(|a| a.len() >= MINIMAL_REGION_SIZE);
        // Sort unconnected regions from largest to smallest
        regions.sort_unstable_by(|a, b| b.len().cmp(&a.len()));

        dug = regions.pop().unwrap().into_iter().collect();

        while let Some(next_region) = regions.pop() {
            // FIXME: Get sorted container for points
            let sorted_dug = sorted(&dug);
            let sorted_region = sorted(&next_region);

            // Add each secondary region to the dug set, carving a tunnel from dug to its random
            // point.
            // XXX: Might be neater to try to minimize the length of the tunnel to carve
            let p1: Point2D = rand::sample(rng, sorted_dug.into_iter(), 1)[0];
            let p2: Point2D = rand::sample(rng, sorted_region.into_iter(), 1)[0];

            dug.extend(next_region.into_iter());
            dug.extend(jaggly_line(rng, p1, p2).into_iter());
        }

        debug_assert!(!dug.is_empty());
        debug_assert!(is_connected(dug.clone()));

        d.dig_chamber(dug.clone());

        // Pick stair sites
        let mut upstair_sites: Vec<Point2D> = self.domain
            .iter()
            .filter(|&&p| is_upstair_pos(&dug, p))
            .cloned()
            .collect();
        upstair_sites.sort_by(pt_ord);

        let mut downstair_sites: Vec<Point2D> = self.domain
            .iter()
            .filter(|&&p| is_downstair_pos(&dug, p))
            .cloned()
            .collect();
        downstair_sites.sort_by(pt_ord);

        d.add_up_stairs(rand::sample(rng, upstair_sites.into_iter(), 1)[0]);
        d.add_down_stairs(rand::sample(rng, downstair_sites.into_iter(), 1)[0]);

        fn is_upstair_pos(dug: &HashSet<Point2D>, pos: Point2D) -> bool {
            // XXX: Enclosure descriptions, still awful to write...
            dug.contains(&(pos + vec2(1, 1))) && !dug.contains(&(pos + vec2(1, 0))) &&
                !dug.contains(&(pos + vec2(0, 1))) &&
                !dug.contains(&(pos + vec2(-1, -1))) &&
                !dug.contains(&(pos + vec2(-1, 0))) &&
                !dug.contains(&(pos + vec2(0, -1)))
        }

        fn is_downstair_pos(dug: &HashSet<Point2D>, pos: Point2D) -> bool {
            // Downstairs needs an extra enclosure behind it for a tile graphics hack.
            dug.contains(&(pos + vec2(-1, -1))) && !dug.contains(&(pos + vec2(-1, 0))) &&
                !dug.contains(&(pos + vec2(0, -1))) &&
                !dug.contains(&(pos + vec2(1, 1))) &&
                !dug.contains(&(pos + vec2(1, 0))) &&
                !dug.contains(&(pos + vec2(0, 1))) &&
                !dug.contains(&(pos + vec2(2, 2))) &&
                !dug.contains(&(pos + vec2(2, 1))) && !dug.contains(&(pos + vec2(1, 2)))
        }
    }
}

fn separate_regions(mut points: HashSet<Point2D>) -> Vec<HashSet<Point2D>> {
    let mut ret = Vec::new();

    while !points.is_empty() {
        let seed = *points.iter().min_by(|a, b| (a.x, a.y).cmp(&(b.x, b.y))).unwrap();
        let subset = flood_fill(points.clone(), seed);
        debug_assert!(!subset.is_empty());
        points = points.difference(&subset).cloned().collect();
        ret.push(subset);
    }

    ret
}

fn flood_fill(mut points: HashSet<Point2D>, seed: Point2D) -> HashSet<Point2D> {
    let mut ret = HashSet::new();
    let mut edge = HashSet::new();

    if !points.remove(&seed) {
        return ret;
    }
    edge.insert(seed);

    while !edge.is_empty() {
        // XXX: Is there a set data type that supports 'pop'?
        let pos = *edge.iter().next().unwrap();
        edge.remove(&pos);
        ret.insert(pos);

        for p in hex_neighbors(pos) {
            if points.contains(&p) {
                debug_assert!(!ret.contains(&p) && !edge.contains(&p));
                points.remove(&p);
                edge.insert(p);
            }
        }
    }

    ret
}

fn is_connected(points: HashSet<Point2D>) -> bool { separate_regions(points).len() <= 1 }

// TODO return impl
fn jaggly_line<R: Rng>(rng: &mut R, p1: Point2D, p2: Point2D) -> Vec<Point2D> {
    let mut ret = Vec::new();
    let mut p = p1;
    ret.push(p);

    while p != p2 {
        let dist = (p2 - p).hex_dist();
        let options = hex_neighbors(p).filter(|&q| (p2 - q).hex_dist() < dist);
        p = rand::sample(rng, options, 1)[0];
        ret.push(p);
    }

    ret
}

// FIXME: Get Points in a fixed-order container to maintain determinism. Failing that, here's a
// helper function for turning a set into an ordered list.
fn sorted(set: &HashSet<Point2D>) -> Vec<Point2D> {
    let mut ret: Vec<Point2D> = set.iter().cloned().collect();
    ret.sort_by(pt_ord);
    ret
}

fn pt_ord(a: &Point2D, b: &Point2D) -> Ordering {
    (a.x, a.y).cmp(&(b.x, b.y))
}
<commit_msg>Prevent jaggly line from digging out of bounds<commit_after>use calx::{RngExt, hex_disc, HexGeom, hex_neighbors};
use euclid::{self, vec2};
use rand::{self, Rng};
use std::collections::HashSet;
use std::cmp::Ordering;

pub type Point2D = euclid::Point2D<i32>;
pub type Size2D = euclid::Size2D<i32>;

pub trait Dungeon {
    type Prefab: Prefab;

    /// Return a random prefab room.
    fn sample_prefab<R: Rng>(&mut self, rng: &mut R) -> Self::Prefab;

    /// Add a large open continuous region to dungeon.
    fn dig_chamber<I: IntoIterator<Item = Point2D>>(&mut self, area: I);

    /// Add a narrow corridor to dungeon.
    fn dig_corridor<I: IntoIterator<Item = Point2D>>(&mut self, path: I);

    fn add_prefab(&mut self, prefab: &Self::Prefab, pos: Point2D);

    fn add_door(&mut self, pos: Point2D);

    fn add_up_stairs(&mut self, pos: Point2D);

    fn add_down_stairs(&mut self, pos: Point2D);
}

pub trait Prefab {
    fn contains(&self, pos: Point2D) -> bool;
    fn can_make_door(&self, pos: Point2D) -> bool;
    fn size(&self) -> Size2D;
}

pub struct DigCavesGen {
    domain: Vec<Point2D>,
}

impl DigCavesGen {
    pub fn new<I: IntoIterator<Item = Point2D>>(domain: I) -> DigCavesGen {
        DigCavesGen { domain: domain.into_iter().collect() }
    }

    pub fn dig<R: Rng, D, P>(&self, rng: &mut R, d: &mut D)
    where
        D: Dungeon<Prefab = P>,
        P: Prefab,
    {
        const INIT_P: f32 = 0.65;
        const N_ITERS: usize = 3;
        const WALL_THRESHOLD: u32 = 3;
        const MINIMAL_REGION_SIZE: usize = 8;

        let available: HashSet<Point2D> = self.domain.iter().cloned().collect();

        // Initial cellular automata run, produces okay looking but usually not fully connected
        // cave map.
        let mut dug: HashSet<Point2D> = self.domain
            .iter()
            .filter(|_| rng.with_chance(INIT_P))
            .cloned()
            .collect();

        for _ in 0..N_ITERS {
            let mut dug2 = dug.clone();

            for &p in &self.domain {
                let n_walls: u32 = hex_disc(p, 1)
                    .filter(|&p2| p2 != p)
                    .map(|p2| !dug.contains(&p2) as u32)
                    .sum();
                let n_walls_2: u32 = hex_disc(p, 2)
                    .filter(|&p2| p2 != p)
                    .map(|p2| !dug.contains(&p2) as u32)
                    .sum();

                // Add a wall if there are either neighboring walls or if the cell is in the
                // centes of a large empty region.
                if n_walls >= WALL_THRESHOLD || n_walls_2 == 0 {
                    dug2.remove(&p);
                } else {
                    dug2.insert(p);
                }
            }

            dug = dug2;
        }

        // Connect separate regions
        let mut regions = separate_regions(dug.clone());
        // Remove uselessly small regions
        regions.retain(|a| a.len() >= MINIMAL_REGION_SIZE);
        // Sort unconnected regions from largest to smallest
        regions.sort_unstable_by(|a, b| b.len().cmp(&a.len()));

        dug = regions.pop().unwrap().into_iter().collect();

        while let Some(next_region) = regions.pop() {
            // FIXME: Get sorted container for points
            let sorted_dug = sorted(&dug);
            let sorted_region = sorted(&next_region);

            // Add each secondary region to the dug set, carving a tunnel from dug to its random
            // point.
            // XXX: Might be neater to try to minimize the length of the tunnel to carve
            let p1: Point2D = rand::sample(rng, sorted_dug.into_iter(), 1)[0];
            let p2: Point2D = rand::sample(rng, sorted_region.into_iter(), 1)[0];

            dug.extend(next_region.into_iter());
            dug.extend(jaggly_line(rng, &available, p1, p2).into_iter());
        }

        debug_assert!(!dug.is_empty());
        debug_assert!(is_connected(dug.clone()));

        d.dig_chamber(dug.clone());

        // Pick stair sites
        let mut upstair_sites: Vec<Point2D> = self.domain
            .iter()
            .filter(|&&p| is_upstair_pos(&dug, p))
            .cloned()
            .collect();
        upstair_sites.sort_by(pt_ord);

        let mut downstair_sites: Vec<Point2D> = self.domain
            .iter()
            .filter(|&&p| is_downstair_pos(&dug, p))
            .cloned()
            .collect();
        downstair_sites.sort_by(pt_ord);

        d.add_up_stairs(rand::sample(rng, upstair_sites.into_iter(), 1)[0]);
        d.add_down_stairs(rand::sample(rng, downstair_sites.into_iter(), 1)[0]);

        fn is_upstair_pos(dug: &HashSet<Point2D>, pos: Point2D) -> bool {
            // XXX: Enclosure descriptions, still awful to write...
            dug.contains(&(pos + vec2(1, 1))) && !dug.contains(&(pos + vec2(1, 0))) &&
                !dug.contains(&(pos + vec2(0, 1))) &&
                !dug.contains(&(pos + vec2(-1, -1))) &&
                !dug.contains(&(pos + vec2(-1, 0))) &&
                !dug.contains(&(pos + vec2(0, -1)))
        }

        fn is_downstair_pos(dug: &HashSet<Point2D>, pos: Point2D) -> bool {
            // Downstairs needs an extra enclosure behind it for a tile graphics hack.
            dug.contains(&(pos + vec2(-1, -1))) && !dug.contains(&(pos + vec2(-1, 0))) &&
                !dug.contains(&(pos + vec2(0, -1))) &&
                !dug.contains(&(pos + vec2(1, 1))) &&
                !dug.contains(&(pos + vec2(1, 0))) &&
                !dug.contains(&(pos + vec2(0, 1))) &&
                !dug.contains(&(pos + vec2(2, 2))) &&
                !dug.contains(&(pos + vec2(2, 1))) && !dug.contains(&(pos + vec2(1, 2)))
        }
    }
}

fn separate_regions(mut points: HashSet<Point2D>) -> Vec<HashSet<Point2D>> {
    let mut ret = Vec::new();

    while !points.is_empty() {
        let seed = *points.iter().min_by(|a, b| (a.x, a.y).cmp(&(b.x, b.y))).unwrap();
        let subset = flood_fill(points.clone(), seed);
        debug_assert!(!subset.is_empty());
        points = points.difference(&subset).cloned().collect();
        ret.push(subset);
    }

    ret
}

fn flood_fill(mut points: HashSet<Point2D>, seed: Point2D) -> HashSet<Point2D> {
    let mut ret = HashSet::new();
    let mut edge = HashSet::new();

    if !points.remove(&seed) {
        return ret;
    }
    edge.insert(seed);

    while !edge.is_empty() {
        // XXX: Is there a set data type that supports 'pop'?
        let pos = *edge.iter().next().unwrap();
        edge.remove(&pos);
        ret.insert(pos);

        for p in hex_neighbors(pos) {
            if points.contains(&p) {
                debug_assert!(!ret.contains(&p) && !edge.contains(&p));
                points.remove(&p);
                edge.insert(p);
            }
        }
    }

    ret
}

fn is_connected(points: HashSet<Point2D>) -> bool { separate_regions(points).len() <= 1 }

// TODO return impl
fn jaggly_line<R: Rng>(rng: &mut R, available: &HashSet<Point2D>, p1: Point2D, p2: Point2D) -> Vec<Point2D> {
    let mut ret = Vec::new();
    let mut p = p1;
    ret.push(p);

    while p != p2 {
        let dist = (p2 - p).hex_dist();
        let options = hex_neighbors(p).filter(|&q| (p2 - q).hex_dist() < dist && available.contains(&q));
        p = rand::sample(rng, options, 1)[0];
        ret.push(p);
    }

    ret
}

// FIXME: Get Points in a fixed-order container to maintain determinism. Failing that, here's a
// helper function for turning a set into an ordered list.
fn sorted(set: &HashSet<Point2D>) -> Vec<Point2D> {
    let mut ret: Vec<Point2D> = set.iter().cloned().collect();
    ret.sort_by(pt_ord);
    ret
}

fn pt_ord(a: &Point2D, b: &Point2D) -> Ordering {
    (a.x, a.y).cmp(&(b.x, b.y))
}
<|endoftext|>