<commit_before>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [::c_uchar; 8usize],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }
}

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;
}
<commit_msg>Fixed struct/constants order<commit_after>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [::c_uchar; 8usize],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }
}

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;
}
<|endoftext|>


<commit_before>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
        Eq | Ne | Lt | Le | Gt | Ge => false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
        Offset | Shl | Shr => false,
    }
}

impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    ///
    /// This is marked `#inline(always)` to work around adverserial codegen when `opt-level = 3`
    #[inline(always)]
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack().is_empty() {
            return Ok(false);
        }

        let loc = match self.frame().loc {
            Ok(loc) => loc,
            Err(_) => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true);
            }
        };
        let basic_block = &self.body().basic_blocks()[loc.block];

        let old_frames = self.frame_idx();

        if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
            assert_eq!(old_frames, self.frame_idx());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.frame_idx());
        self.terminator(terminator)?;
        Ok(true)
    }

    /// Runs the interpretation logic for the given `mir::Statement` at the current frame and
    /// statement counter. This also moves the statement counter forward.
    pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc_middle::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.frame_idx();

        match &stmt.kind {
            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,

            SetDiscriminant { place, variant_index } => {
                let dest = self.eval_place(**place)?;
                self.write_discriminant(*variant_index, &dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                self.storage_live(*local)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                self.storage_dead(*local)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, place) => {
                let dest = self.eval_place(**place)?;
                M::retag(self, *kind, &dest)?;
            }

            // Call CopyNonOverlapping
            CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => {
                let src = self.eval_operand(src, None)?;
                let dst = self.eval_operand(dst, None)?;
                let count = self.eval_operand(count, None)?;
                self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Currently, Miri discards Coverage statements. Coverage statements are only injected
            // via an optional compile time MIR pass and have no side effects. Since Coverage
            // statements don't exist at the source level, it is safe for Miri to ignore them, even
            // for undefined behavior (UB) checks.
            //
            // A coverage counter inside a const expression (for example, a counter injected in a
            // const function) is discarded when the const is evaluated at compile time. Whether
            // this should change, and/or how to implement a const eval counter, is a subject of the
            // following issue:
            //
            // FIXME(#73156): Handle source code coverage in const eval
            Coverage(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc_middle::mir::Rvalue::*;
        match *rvalue {
            ThreadLocalRef(did) => {
                let ptr = M::thread_local_static_base_pointer(self, did)?;
                self.write_pointer(ptr, &dest)?;
            }

            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(&op, &dest)?;
            }

            BinaryOp(bin_op, box (ref left, ref right)) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
            }

            CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(&self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(bin_op, &left, &right, &dest)?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, &val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, &dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                // active_field_index is for union initialization.
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant(variant_index, &dest)?;
                        if adt_def.is_enum() {
                            assert!(active_field_index.is_none());
                            (self.place_downcast(&dest, variant_index)?, None)
                        } else {
                            if active_field_index.is_some() {
                                assert_eq!(operands.len(), 1);
                            }
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None),
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    let field_index = active_field_index.unwrap_or(i);
                    let field_dest = self.place_field(&dest, field_index)?;
                    self.copy_op(&op, &field_dest)?;
                }
            }

            Repeat(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                assert!(!src.layout.is_unsized());
                let dest = self.force_allocation(&dest)?;
                let length = dest.len(self)?;

                if length == 0 {
                    // Nothing to copy... but let's still make sure that `dest` as a place is valid.
                    self.get_alloc_mut(&dest)?;
                } else {
                    // Write the src to the first element.
                    let first = self.mplace_field(&dest, 0)?;
                    self.copy_op(&src, &first.into())?;

                    // This is performance-sensitive code for big static/const arrays! So we
                    // avoid writing each operand individually and instead just make many copies
                    // of the first element.
                    let elem_size = first.layout.size;
                    let first_ptr = first.ptr;
                    let rest_ptr = first_ptr.offset(elem_size, self)?;
                    self.memory.copy_repeatedly(
                        first_ptr,
                        first.align,
                        rest_ptr,
                        first.align,
                        elem_size,
                        length - 1,
                        /*nonoverlapping:*/ true,
                    )?;
                }
            }

            Len(place) => {
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(&src)?;
                let len = mplace.len(self)?;
                self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
            }

            AddressOf(_, place) | Ref(_, _, place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(&src)?;
                self.write_immediate(place.to_ref(self), &dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, &dest)?;
            }

            NullaryOp(null_op, ty) => {
                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                if layout.is_unsized() {
                    // FIXME: This should be a span_bug (#80742)
                    self.tcx.sess.delay_span_bug(
                        self.frame().current_span(),
                        &format!("Nullary MIR operator called for unsized type {}", ty),
                    );
                    throw_inval!(SizeOfUnsizedType(ty));
                }
                let val = match null_op {
                    mir::NullOp::SizeOf => layout.size.bytes(),
                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
                    mir::NullOp::Box => unreachable!(),
                };
                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
            }

            ShallowInitBox(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                let v = self.read_immediate(&src)?;
                self.write_immediate(*v, &dest)?;
            }

            Cast(cast_kind, ref operand, cast_ty) => {
                let src = self.eval_operand(operand, None)?;
                let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
                self.cast(&src, cast_kind, cast_ty, &dest)?;
            }

            Discriminant(place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(&op)?.0;
                self.write_scalar(discr_val, &dest)?;
            }
        }

        trace!("{:?}", self.dump_place(*dest));

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);

        self.eval_terminator(terminator)?;
        if !self.stack().is_empty() {
            if let Ok(loc) = self.frame().loc {
                info!("// executing {:?}", loc.block);
            }
        }
        Ok(())
    }
}
<commit_msg>Rollup merge of #91303 - RalfJung:array-init-align, r=oli-obk<commit_after>//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;

use super::{InterpCx, Machine};

/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
/// same type as the result.
#[inline]
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
        Eq | Ne | Lt | Le | Gt | Ge => false,
    }
}
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
/// same type as the LHS.
#[inline]
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
    use rustc_middle::mir::BinOp::*;
    match op {
        Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
        Offset | Shl | Shr => false,
    }
}

impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    pub fn run(&mut self) -> InterpResult<'tcx> {
        while self.step()? {}
        Ok(())
    }

    /// Returns `true` as long as there are more things to do.
    ///
    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    ///
    /// This is marked `#inline(always)` to work around adverserial codegen when `opt-level = 3`
    #[inline(always)]
    pub fn step(&mut self) -> InterpResult<'tcx, bool> {
        if self.stack().is_empty() {
            return Ok(false);
        }

        let loc = match self.frame().loc {
            Ok(loc) => loc,
            Err(_) => {
                // We are unwinding and this fn has no cleanup code.
                // Just go on unwinding.
                trace!("unwinding: skipping frame");
                self.pop_stack_frame(/* unwinding */ true)?;
                return Ok(true);
            }
        };
        let basic_block = &self.body().basic_blocks()[loc.block];

        let old_frames = self.frame_idx();

        if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
            assert_eq!(old_frames, self.frame_idx());
            self.statement(stmt)?;
            return Ok(true);
        }

        M::before_terminator(self)?;

        let terminator = basic_block.terminator();
        assert_eq!(old_frames, self.frame_idx());
        self.terminator(terminator)?;
        Ok(true)
    }

    /// Runs the interpretation logic for the given `mir::Statement` at the current frame and
    /// statement counter. This also moves the statement counter forward.
    pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", stmt);

        use rustc_middle::mir::StatementKind::*;

        // Some statements (e.g., box) push new stack frames.
        // We have to record the stack frame number *before* executing the statement.
        let frame_idx = self.frame_idx();

        match &stmt.kind {
            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,

            SetDiscriminant { place, variant_index } => {
                let dest = self.eval_place(**place)?;
                self.write_discriminant(*variant_index, &dest)?;
            }

            // Mark locals as alive
            StorageLive(local) => {
                self.storage_live(*local)?;
            }

            // Mark locals as dead
            StorageDead(local) => {
                self.storage_dead(*local)?;
            }

            // No dynamic semantics attached to `FakeRead`; MIR
            // interpreter is solely intended for borrowck'ed code.
            FakeRead(..) => {}

            // Stacked Borrows.
            Retag(kind, place) => {
                let dest = self.eval_place(**place)?;
                M::retag(self, *kind, &dest)?;
            }

            // Call CopyNonOverlapping
            CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { src, dst, count }) => {
                let src = self.eval_operand(src, None)?;
                let dst = self.eval_operand(dst, None)?;
                let count = self.eval_operand(count, None)?;
                self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
            }

            // Statements we do not track.
            AscribeUserType(..) => {}

            // Currently, Miri discards Coverage statements. Coverage statements are only injected
            // via an optional compile time MIR pass and have no side effects. Since Coverage
            // statements don't exist at the source level, it is safe for Miri to ignore them, even
            // for undefined behavior (UB) checks.
            //
            // A coverage counter inside a const expression (for example, a counter injected in a
            // const function) is discarded when the const is evaluated at compile time. Whether
            // this should change, and/or how to implement a const eval counter, is a subject of the
            // following issue:
            //
            // FIXME(#73156): Handle source code coverage in const eval
            Coverage(..) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}

            LlvmInlineAsm { .. } => throw_unsup_format!("inline assembly is not supported"),
        }

        self.stack_mut()[frame_idx].loc.as_mut().unwrap().statement_index += 1;
        Ok(())
    }

    /// Evaluate an assignment statement.
    ///
    /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
    /// type writes its results directly into the memory specified by the place.
    pub fn eval_rvalue_into_place(
        &mut self,
        rvalue: &mir::Rvalue<'tcx>,
        place: mir::Place<'tcx>,
    ) -> InterpResult<'tcx> {
        let dest = self.eval_place(place)?;

        use rustc_middle::mir::Rvalue::*;
        match *rvalue {
            ThreadLocalRef(did) => {
                let ptr = M::thread_local_static_base_pointer(self, did)?;
                self.write_pointer(ptr, &dest)?;
            }

            Use(ref operand) => {
                // Avoid recomputing the layout
                let op = self.eval_operand(operand, Some(dest.layout))?;
                self.copy_op(&op, &dest)?;
            }

            BinaryOp(bin_op, box (ref left, ref right)) => {
                let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
                let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
            }

            CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
                // Due to the extra boolean in the result, we can never reuse the `dest.layout`.
                let left = self.read_immediate(&self.eval_operand(left, None)?)?;
                let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
                let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
                self.binop_with_overflow(bin_op, &left, &right, &dest)?;
            }

            UnaryOp(un_op, ref operand) => {
                // The operand always has the same type as the result.
                let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
                let val = self.unary_op(un_op, &val)?;
                assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
                self.write_immediate(*val, &dest)?;
            }

            Aggregate(ref kind, ref operands) => {
                // active_field_index is for union initialization.
                let (dest, active_field_index) = match **kind {
                    mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
                        self.write_discriminant(variant_index, &dest)?;
                        if adt_def.is_enum() {
                            assert!(active_field_index.is_none());
                            (self.place_downcast(&dest, variant_index)?, None)
                        } else {
                            if active_field_index.is_some() {
                                assert_eq!(operands.len(), 1);
                            }
                            (dest, active_field_index)
                        }
                    }
                    _ => (dest, None),
                };

                for (i, operand) in operands.iter().enumerate() {
                    let op = self.eval_operand(operand, None)?;
                    let field_index = active_field_index.unwrap_or(i);
                    let field_dest = self.place_field(&dest, field_index)?;
                    self.copy_op(&op, &field_dest)?;
                }
            }

            Repeat(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                assert!(!src.layout.is_unsized());
                let dest = self.force_allocation(&dest)?;
                let length = dest.len(self)?;

                if length == 0 {
                    // Nothing to copy... but let's still make sure that `dest` as a place is valid.
                    self.get_alloc_mut(&dest)?;
                } else {
                    // Write the src to the first element.
                    let first = self.mplace_field(&dest, 0)?;
                    self.copy_op(&src, &first.into())?;

                    // This is performance-sensitive code for big static/const arrays! So we
                    // avoid writing each operand individually and instead just make many copies
                    // of the first element.
                    let elem_size = first.layout.size;
                    let first_ptr = first.ptr;
                    let rest_ptr = first_ptr.offset(elem_size, self)?;
                    // For the alignment of `rest_ptr`, we crucially do *not* use `first.align` as
                    // that place might be more aligned than its type mandates (a `u8` array could
                    // be 4-aligned if it sits at the right spot in a struct). Instead we use
                    // `first.layout.align`, i.e., the alignment given by the type.
                    self.memory.copy_repeatedly(
                        first_ptr,
                        first.align,
                        rest_ptr,
                        first.layout.align.abi,
                        elem_size,
                        length - 1,
                        /*nonoverlapping:*/ true,
                    )?;
                }
            }

            Len(place) => {
                let src = self.eval_place(place)?;
                let mplace = self.force_allocation(&src)?;
                let len = mplace.len(self)?;
                self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
            }

            AddressOf(_, place) | Ref(_, _, place) => {
                let src = self.eval_place(place)?;
                let place = self.force_allocation(&src)?;
                self.write_immediate(place.to_ref(self), &dest)?;
            }

            NullaryOp(mir::NullOp::Box, _) => {
                M::box_alloc(self, &dest)?;
            }

            NullaryOp(null_op, ty) => {
                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                let layout = self.layout_of(ty)?;
                if layout.is_unsized() {
                    // FIXME: This should be a span_bug (#80742)
                    self.tcx.sess.delay_span_bug(
                        self.frame().current_span(),
                        &format!("Nullary MIR operator called for unsized type {}", ty),
                    );
                    throw_inval!(SizeOfUnsizedType(ty));
                }
                let val = match null_op {
                    mir::NullOp::SizeOf => layout.size.bytes(),
                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
                    mir::NullOp::Box => unreachable!(),
                };
                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
            }

            ShallowInitBox(ref operand, _) => {
                let src = self.eval_operand(operand, None)?;
                let v = self.read_immediate(&src)?;
                self.write_immediate(*v, &dest)?;
            }

            Cast(cast_kind, ref operand, cast_ty) => {
                let src = self.eval_operand(operand, None)?;
                let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
                self.cast(&src, cast_kind, cast_ty, &dest)?;
            }

            Discriminant(place) => {
                let op = self.eval_place_to_op(place, None)?;
                let discr_val = self.read_discriminant(&op)?.0;
                self.write_scalar(discr_val, &dest)?;
            }
        }

        trace!("{:?}", self.dump_place(*dest));

        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
        info!("{:?}", terminator.kind);

        self.eval_terminator(terminator)?;
        if !self.stack().is_empty() {
            if let Ok(loc) = self.frame().loc {
                info!("// executing {:?}", loc.block);
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use test::Bencher;

#[bench]
fn bench_with_capacity(b: &mut Bencher) {
    b.iter(|| String::with_capacity(100));
}

#[bench]
fn bench_push_str(b: &mut Bencher) {
    let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
    b.iter(|| {
        let mut r = String::new();
        r.push_str(s);
    });
}

const REPETITIONS: u64 = 10_000;

#[bench]
fn bench_push_str_one_byte(b: &mut Bencher) {
    b.bytes = REPETITIONS;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push_str("a")
        }
    });
}

#[bench]
fn bench_push_char_one_byte(b: &mut Bencher) {
    b.bytes = REPETITIONS;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push('a')
        }
    });
}

#[bench]
fn bench_push_char_two_bytes(b: &mut Bencher) {
    b.bytes = REPETITIONS * 2;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push('â')
        }
    });
}

#[bench]
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
    let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
              Lorem ipsum dolor sit amet, consectetur. ";

    assert_eq!(100, s.len());
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
    let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
    assert_eq!(100, s.len());
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_invalid(b: &mut Bencher) {
    let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
    let s = repeat(0xf5).take(100).collect::<Vec<_>>();
    b.iter(|| {
        let _ = String::from_utf8_lossy(&s);
    });
}

#[bench]
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    // ensure our operation produces an exact-size string before we benchmark it
    let mut r = String::with_capacity(s.len());
    r.push_str(s);
    assert_eq!(r.len(), r.capacity());
    b.iter(|| {
        let mut r = String::with_capacity(s.len());
        r.push_str(s);
        r.shrink_to_fit();
        r
    });
}

#[bench]
fn bench_from_str(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| String::from(s))
}

#[bench]
fn bench_from(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| String::from(s))
}

#[bench]
fn bench_to_string(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| s.to_string())
}
<commit_msg>Rollup merge of #67281 - llogiq:nonoverlapping-insert, r=alexcrichton<commit_after>use std::iter::repeat;
use test::Bencher;

#[bench]
fn bench_with_capacity(b: &mut Bencher) {
    b.iter(|| String::with_capacity(100));
}

#[bench]
fn bench_push_str(b: &mut Bencher) {
    let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
    b.iter(|| {
        let mut r = String::new();
        r.push_str(s);
    });
}

const REPETITIONS: u64 = 10_000;

#[bench]
fn bench_push_str_one_byte(b: &mut Bencher) {
    b.bytes = REPETITIONS;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push_str("a")
        }
    });
}

#[bench]
fn bench_push_char_one_byte(b: &mut Bencher) {
    b.bytes = REPETITIONS;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push('a')
        }
    });
}

#[bench]
fn bench_push_char_two_bytes(b: &mut Bencher) {
    b.bytes = REPETITIONS * 2;
    b.iter(|| {
        let mut r = String::new();
        for _ in 0..REPETITIONS {
            r.push('â')
        }
    });
}

#[bench]
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
    let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
              Lorem ipsum dolor sit amet, consectetur. ";

    assert_eq!(100, s.len());
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
    let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
    assert_eq!(100, s.len());
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_invalid(b: &mut Bencher) {
    let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
    b.iter(|| {
        let _ = String::from_utf8_lossy(s);
    });
}

#[bench]
fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
    let s = repeat(0xf5).take(100).collect::<Vec<_>>();
    b.iter(|| {
        let _ = String::from_utf8_lossy(&s);
    });
}

#[bench]
fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    // ensure our operation produces an exact-size string before we benchmark it
    let mut r = String::with_capacity(s.len());
    r.push_str(s);
    assert_eq!(r.len(), r.capacity());
    b.iter(|| {
        let mut r = String::with_capacity(s.len());
        r.push_str(s);
        r.shrink_to_fit();
        r
    });
}

#[bench]
fn bench_from_str(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| String::from(s))
}

#[bench]
fn bench_from(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| String::from(s))
}

#[bench]
fn bench_to_string(b: &mut Bencher) {
    let s = "Hello there, the quick brown fox jumped over the lazy dog! \
             Lorem ipsum dolor sit amet, consectetur. ";
    b.iter(|| s.to_string())
}

#[bench]
fn bench_insert_char_short(b: &mut Bencher) {
    let s = "Hello, World!";
    b.iter(|| {
        let mut x = String::from(s);
        black_box(&mut x).insert(6, black_box(' '));
        x
    })
}

#[bench]
fn bench_insert_char_long(b: &mut Bencher) {
    let s = "Hello, World!";
    b.iter(|| {
        let mut x = String::from(s);
        black_box(&mut x).insert(6, black_box('❤'));
        x
    })
}

#[bench]
fn bench_insert_str_short(b: &mut Bencher) {
    let s = "Hello, World!";
    b.iter(|| {
        let mut x = String::from(s);
        black_box(&mut x).insert_str(6, black_box(" "));
        x
    })
}

#[bench]
fn bench_insert_str_long(b: &mut Bencher) {
    let s = "Hello, World!";
    b.iter(|| {
        let mut x = String::from(s);
        black_box(&mut x).insert_str(6, black_box(" rustic "));
        x
    })
}
<|endoftext|>


<commit_before>use super::*;
use crate::{inner::*, norm::*};
use num_traits::{One, Zero};

/// Calc a reflactor `w` from a vector `x`
pub fn calc_reflector(x: &mut ArrayBase<S, Ix1>)
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    let norm = x.norm_l2();
    let alpha = x[0].mul_real(norm / x[0].abs());
    x[0] -= alpha;
    let inv_rev_norm = A::Real::one() / x.norm_l2();
    azip!(mut a(x) in { *a = a.mul_real(inv_rev_norm)});
}

/// Take a reflection using `w`
pub fn reflect(w: &ArrayBase<S1, Ix1>, a: &mut ArrayBase<S2, Ix1>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    assert_eq!(w.len(), a.len());
    let n = a.len();
    let c = A::from(2.0).unwrap() * w.inner(&a);
    for l in 0..n {
        a[l] -= c * w[l];
    }
}

/// Iterative orthogonalizer using Householder reflection
#[derive(Debug, Clone)]
pub struct Householder {
    /// Dimension of orthogonalizer
    dim: usize,

    /// Store Householder reflector.
    ///
    /// The coefficient is copied into another array, and this does not contain
    v: Vec<Array1>,
}

impl Householder {
    /// Create a new orthogonalizer
    pub fn new(dim: usize) -> Self {
        Householder { dim, v: Vec::new() }
    }

    /// Take a Reflection `P = I - 2ww^T`
    fn fundamental_reflection<S>(&self, k: usize, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(k < self.v.len());
        assert_eq!(a.len(), self.dim, "Input array size mismaches to the dimension");
        reflect(&self.v[k].slice(s![k..]), &mut a.slice_mut(s![k..]));
    }

    /// Take forward reflection `P = P_l ... P_1`
    pub fn forward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(a.len() == self.dim);
        let l = self.v.len();
        for k in 0..l {
            self.fundamental_reflection(k, a);
        }
    }

    /// Take backward reflection `P = P_1 ... P_l`
    pub fn backward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(a.len() == self.dim);
        let l = self.v.len();
        for k in (0..l).rev() {
            self.fundamental_reflection(k, a);
        }
    }

    fn eval_residual<S>(&self, a: &ArrayBase<S, Ix1>) -> A::Real
    where
        S: Data<Elem = A>,
    {
        let l = self.v.len();
        if l == self.dim {
            Zero::zero()
        } else {
            a.slice(s![l..]).norm_l2()
        }
    }
}

impl Orthogonalizer for Householder {
    type Elem = A;

    fn dim(&self) -> usize {
        self.dim
    }

    fn len(&self) -> usize {
        self.v.len()
    }

    fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Array1
    where
        S: Data<Elem = A>,
    {
        let mut a = a.into_owned();
        self.forward_reflection(&mut a);
        let res = self.eval_residual(&a);
        let k = self.len();
        let mut c = Array1::zeros(k + 1);
        azip!(mut c(c.slice_mut(s![..k])), a(a.slice(s![..k])) in { *c = a });
        c[k] = A::from_real(res);
        c
    }

    fn append<S>(&mut self, mut a: ArrayBase<S, Ix1>, rtol: A::Real) -> Result<Array1, Array1>
    where
        S: DataMut<Elem = A>,
    {
        assert_eq!(a.len(), self.dim);
        let k = self.len();
        self.forward_reflection(&mut a);
        let alpha = self.eval_residual(&a);
        let mut coef = Array::zeros(k + 1);
        for i in 0..k {
            coef[i] = a[i];
        }
        coef[k] = A::from_real(alpha);
        if alpha < rtol {
            // linearly dependent
            return Err(coef);
        }

        assert!(k < a.len()); // this must hold because `alpha == 0` if k >= a.len()

        // Add reflector
        let alpha = if a[k].abs() > Zero::zero() {
            a[k].mul_real(alpha / a[k].abs())
        } else {
            A::from_real(alpha)
        };
        coef[k] = alpha;

        a[k] -= alpha;
        let norm = a.slice(s![k..]).norm_l2();
        azip!(mut a (a.slice_mut(s![..k])) in { *a = Zero::zero() }); // this can be omitted
        azip!(mut a (a.slice_mut(s![k..])) in { *a = a.div_real(norm) });
        self.v.push(a.into_owned());
        Ok(coef)
    }

    fn get_q(&self) -> Q {
        assert!(self.len() > 0);
        let mut a = Array::zeros((self.dim(), self.len()));
        for (i, mut col) in a.axis_iter_mut(Axis(1)).enumerate() {
            col[i] = A::one();
            self.backward_reflection(&mut col);
        }
        a
    }
}

/// Online QR decomposition of vectors
pub fn householder(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy,
) -> (Q, R)
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    let h = Householder::new(dim);
    qr(iter, h, rtol, strategy)
}

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

    #[test]
    fn check_reflector() {
        let mut a = array![c64::new(1.0, 1.0), c64::new(1.0, 0.0), c64::new(0.0, 1.0)];
        let mut w = a.clone();
        calc_reflector(&mut w);
        reflect(&w, &mut a);
        close_l2(
            &a,
            &array![c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()],
            1e-9,
        );
    }
}
<commit_msg>Fix reflection bug<commit_after>use super::*;
use crate::{inner::*, norm::*};
use num_traits::{One, Zero};

/// Calc a reflactor `w` from a vector `x`
pub fn calc_reflector(x: &mut ArrayBase<S, Ix1>)
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    let norm = x.norm_l2();
    let alpha = -x[0].mul_real(norm / x[0].abs());
    x[0] -= alpha;
    let inv_rev_norm = A::Real::one() / x.norm_l2();
    azip!(mut a(x) in { *a = a.mul_real(inv_rev_norm)});
}

/// Take a reflection using `w`
pub fn reflect(w: &ArrayBase<S1, Ix1>, a: &mut ArrayBase<S2, Ix1>)
where
    A: Scalar + Lapack,
    S1: Data<Elem = A>,
    S2: DataMut<Elem = A>,
{
    assert_eq!(w.len(), a.len());
    let n = a.len();
    let c = A::from(2.0).unwrap() * w.inner(&a);
    for l in 0..n {
        a[l] -= c * w[l];
    }
}

/// Iterative orthogonalizer using Householder reflection
#[derive(Debug, Clone)]
pub struct Householder {
    /// Dimension of orthogonalizer
    dim: usize,

    /// Store Householder reflector.
    ///
    /// The coefficient is copied into another array, and this does not contain
    v: Vec<Array1>,
}

impl Householder {
    /// Create a new orthogonalizer
    pub fn new(dim: usize) -> Self {
        Householder { dim, v: Vec::new() }
    }

    /// Take a Reflection `P = I - 2ww^T`
    fn fundamental_reflection<S>(&self, k: usize, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(k < self.v.len());
        assert_eq!(a.len(), self.dim, "Input array size mismaches to the dimension");
        reflect(&self.v[k].slice(s![k..]), &mut a.slice_mut(s![k..]));
    }

    /// Take forward reflection `P = P_l ... P_1`
    pub fn forward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(a.len() == self.dim);
        let l = self.v.len();
        for k in 0..l {
            self.fundamental_reflection(k, a);
        }
    }

    /// Take backward reflection `P = P_1 ... P_l`
    pub fn backward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
    where
        S: DataMut<Elem = A>,
    {
        assert!(a.len() == self.dim);
        let l = self.v.len();
        for k in (0..l).rev() {
            self.fundamental_reflection(k, a);
        }
    }

    fn eval_residual<S>(&self, a: &ArrayBase<S, Ix1>) -> A::Real
    where
        S: Data<Elem = A>,
    {
        let l = self.v.len();
        a.slice(s![l..]).norm_l2()
    }
}

impl Orthogonalizer for Householder {
    type Elem = A;

    fn dim(&self) -> usize {
        self.dim
    }

    fn len(&self) -> usize {
        self.v.len()
    }

    fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Array1
    where
        S: Data<Elem = A>,
    {
        let mut a = a.into_owned();
        self.forward_reflection(&mut a);
        let res = self.eval_residual(&a);
        let k = self.len();
        let mut c = Array1::zeros(k + 1);
        azip!(mut c(c.slice_mut(s![..k])), a(a.slice(s![..k])) in { *c = a });
        c[k] = A::from_real(res);
        c
    }

    fn append<S>(&mut self, mut a: ArrayBase<S, Ix1>, rtol: A::Real) -> Result<Array1, Array1>
    where
        S: DataMut<Elem = A>,
    {
        assert_eq!(a.len(), self.dim);

        self.forward_reflection(&mut a);

        let k = self.len();
        let alpha = self.eval_residual(&a);
        let alpha = if k  Zero::zero() {
            -a[k].mul_real(alpha / a[k].abs())
        } else {
            A::from_real(alpha)
        };

        let mut coef = Array::zeros(k + 1);
        for i in 0..k {
            coef[i] = a[i];
        }
        coef[k] = alpha;

        if alpha.abs() < rtol {
            // linearly dependent
            return Err(coef);
        }

        assert!(k < a.len()); // this must hold because `alpha == 0` if k >= a.len()

        // Add reflector
        a[k] -= alpha;
        let norm = a.slice(s![k..]).norm_l2();
        azip!(mut a (a.slice_mut(s![..k])) in { *a = A::zero() });
        azip!(mut a (a.slice_mut(s![k..])) in { *a = a.div_real(norm) });
        self.v.push(a.into_owned());
        Ok(coef)
    }

    fn get_q(&self) -> Q {
        assert!(self.len() > 0);
        let mut a = Array::zeros((self.dim(), self.len()));
        for (i, mut col) in a.axis_iter_mut(Axis(1)).enumerate() {
            col[i] = A::one();
            self.backward_reflection(&mut col);
        }
        a
    }
}

/// Online QR decomposition of vectors
pub fn householder(
    iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
    dim: usize,
    rtol: A::Real,
    strategy: Strategy,
) -> (Q, R)
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    let h = Householder::new(dim);
    qr(iter, h, rtol, strategy)
}

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

    #[test]
    fn check_reflector() {
        let mut a = array![c64::new(1.0, 1.0), c64::new(1.0, 0.0), c64::new(0.0, 1.0)];
        let mut w = a.clone();
        calc_reflector(&mut w);
        reflect(&w, &mut a);
        close_l2(
            &a,
            &array![-c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()],
            1e-9,
        );
    }
}
<|endoftext|>


<commit_before>//!An example of generating julia fractals.

extern crate num;
extern crate image;

use std::io::File;

use num::complex::Complex;

// The GenericImage trait provides the method put_pixel.
use image::GenericImage;

fn main() {
        let max_iterations = 256u16;

        let imgx = 800;
        let imgy = 800;

        let scalex = 4.0 / imgx as f32;
        let scaley = 4.0 / imgy as f32;

        //Create a new ImgBuf with width: imgx and height: imgy
        let mut imbuf = image::ImageBuffer::new(imgx, imgy);

        for y in range(0, imgy) {
                let cy = y as f32 * scaley - 2.0;

                for x in range(0, imgx) {
                        let cx = x as f32 * scalex - 2.0;

                        let mut z = Complex::new(cx, cy);
                        let c = Complex::new(-0.4, 0.6);

                        let mut i = 0;

                        for t in range(0, max_iterations) {
                                if z.norm() > 2.0 {
                                        break
                                }

                                z = z * z + c;
                                i = t;
                        }

                        // Create an 8bit pixel of type Luma and value i
                        let pixel = image::Luma([i as u8]);

                        // Put a pixel in the image at coordinates x and y
                        imbuf.put_pixel(x, y, pixel);
                }
        }

        // Save the image as "fractal.png"
        let fout = File::create(&Path::new("fractal.png")).unwrap();

        //We must indicate the image's color type and what format to save as.
        let _    = image::ImageLuma8(imbuf).save(fout, image::PNG);
}<commit_msg>show off iterators<commit_after>//!An example of generating julia fractals.

extern crate num;
extern crate image;

use std::io::File;

use num::complex::Complex;

fn main() {
    let max_iterations = 256u16;

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = y as f32 * scaley - 2.0;
        let cx = x as f32 * scalex - 2.0;

        let mut z = Complex::new(cx, cy);
        let c = Complex::new(-0.4, 0.6);

        let mut i = 0;

        for t in range(0, max_iterations) {
            if z.norm() > 2.0 {
                break
            }
            z = z * z + c;
            i = t;
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([i as u8]);

    }

    // Save the image as “fractal.png”
    let fout = File::create(&Path::new("fractal.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _    = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![allow(clippy::useless_attribute)] //issue #2910

#[macro_use]
extern crate serde_derive;

/// Test that we do not lint for unused underscores in a `MacroAttribute`
/// expansion
#[deny(clippy::used_underscore_binding)]
#[derive(Deserialize)]
struct MacroAttributesTest {
    _foo: u32,
}

#[test]
fn macro_attributes_test() {
    let _ = MacroAttributesTest { _foo: 0 };
}

fn main() {}
<commit_msg>tests: used_underscore_binding_macro: disable random_state lint.<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![allow(clippy::useless_attribute)] //issue #2910
#![allow(clippy::random_state)] // issue #3628

#[macro_use]
extern crate serde_derive;

/// Test that we do not lint for unused underscores in a `MacroAttribute`
/// expansion
#[deny(clippy::used_underscore_binding)]
#[derive(Deserialize)]
struct MacroAttributesTest {
    _foo: u32,
}

#[test]
fn macro_attributes_test() {
    let _ = MacroAttributesTest { _foo: 0 };
}

fn main() {}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use utils::{CLONE_PATH, OPTION_PATH};
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};

/// **What it does:** This lint checks for mapping clone() over an iterator. It is `Warn` by default and suggests to use `.cloned()` instead.
///
/// **Why is this bad?** It makes the code less readable.
///
/// **Known problems:** False negative: The lint currently misses mapping `Clone::clone` directly. Issue #436 is tracking this.
///
/// **Example:** `x.map(|e| e.clone());`
declare_lint!(pub MAP_CLONE, Warn,
              "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \
              `.cloned()` instead)");

#[derive(Copy, Clone)]
pub struct MapClonePass;

impl LateLintPass for MapClonePass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        // call to .map()
        if let ExprMethodCall(name, _, ref args) = expr.node {
            if name.node.as_str() == "map" && args.len() == 2 {
                match args[1].node {
                    ExprClosure(_, ref decl, ref blk) => {
                        if_let_chain! {
                            [
                            // just one expression in the closure
                            blk.stmts.is_empty(),
                            let Some(ref closure_expr) = blk.expr,
                            // nothing special in the argument, besides reference bindings
                            // (e.g. .map(|&x| x) )
                            let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
                            // the method is being called on a known type (option or iterator)
                            let Some(type_name) = get_type_name(cx, expr, &args[0])
                            ], {
                                // look for derefs, for .map(|x| *x)
                                if only_derefs(cx, &*closure_expr, arg_ident) &&
                                    // .cloned() only removes one level of indirection, don't lint on more
                                    walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1
                                {
                                    span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                        "you seem to be using .map() to clone the contents of an {}, consider \
                                        using `.cloned()`", type_name),
                                        &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                                }
                                // explicit clone() calls ( .map(|x| x.clone()) )
                                else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node {
                                    if clone_call.node.as_str() == "clone" &&
                                        clone_args.len() == 1 &&
                                        match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) &&
                                        expr_eq_ident(&clone_args[0], arg_ident)
                                    {
                                        span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                            "you seem to be using .map() to clone the contents of an {}, consider \
                                            using `.cloned()`", type_name),
                                            &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                                    }
                                }
                            }
                        }
                    }
                    ExprPath(_, ref path) => {
                        if match_path(path, &CLONE_PATH) {
                            let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
                            span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                "you seem to be using .map() to clone the contents of an {}, consider \
                                using `.cloned()`", type_name),
                                &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                        }
                    }
                    _ => (),
                }
            }
        }
    }
}

fn expr_eq_ident(expr: &Expr, id: Ident) -> bool {
    match expr.node {
        ExprPath(None, ref path) => {
            let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }];
            !path.global && path.segments[..] == arg_segment
        }
        _ => false,
    }
}

fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
    if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) {
        Some("iterator")
    } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &OPTION_PATH) {
        Some("Option")
    } else {
        None
    }
}

fn get_arg_name(pat: &Pat) -> Option<Ident> {
    match pat.node {
        PatIdent(_, ident, None) => Some(ident.node),
        PatRegion(ref subpat, _) => get_arg_name(subpat),
        _ => None,
    }
}

fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool {
    match expr.node {
        ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => {
            only_derefs(cx, subexpr, id)
        }
        _ => expr_eq_ident(expr, id),
    }
}

impl LintPass for MapClonePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(MAP_CLONE)
    }
}
<commit_msg>Remove reference to a fixed issue<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use utils::{CLONE_PATH, OPTION_PATH};
use utils::{is_adjusted, match_path, match_trait_method, match_type, snippet, span_help_and_lint};
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};

/// **What it does:** This lint checks for mapping clone() over an iterator. It is `Warn` by default and suggests to use `.cloned()` instead.
///
/// **Why is this bad?** It makes the code less readable.
///
/// **Known problems:** None
///
/// **Example:** `x.map(|e| e.clone());`
declare_lint!(pub MAP_CLONE, Warn,
              "using `.map(|x| x.clone())` to clone an iterator or option's contents (recommends \
              `.cloned()` instead)");

#[derive(Copy, Clone)]
pub struct MapClonePass;

impl LateLintPass for MapClonePass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        // call to .map()
        if let ExprMethodCall(name, _, ref args) = expr.node {
            if name.node.as_str() == "map" && args.len() == 2 {
                match args[1].node {
                    ExprClosure(_, ref decl, ref blk) => {
                        if_let_chain! {
                            [
                            // just one expression in the closure
                            blk.stmts.is_empty(),
                            let Some(ref closure_expr) = blk.expr,
                            // nothing special in the argument, besides reference bindings
                            // (e.g. .map(|&x| x) )
                            let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
                            // the method is being called on a known type (option or iterator)
                            let Some(type_name) = get_type_name(cx, expr, &args[0])
                            ], {
                                // look for derefs, for .map(|x| *x)
                                if only_derefs(cx, &*closure_expr, arg_ident) &&
                                    // .cloned() only removes one level of indirection, don't lint on more
                                    walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1
                                {
                                    span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                        "you seem to be using .map() to clone the contents of an {}, consider \
                                        using `.cloned()`", type_name),
                                        &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                                }
                                // explicit clone() calls ( .map(|x| x.clone()) )
                                else if let ExprMethodCall(clone_call, _, ref clone_args) = closure_expr.node {
                                    if clone_call.node.as_str() == "clone" &&
                                        clone_args.len() == 1 &&
                                        match_trait_method(cx, closure_expr, &["core", "clone", "Clone"]) &&
                                        expr_eq_ident(&clone_args[0], arg_ident)
                                    {
                                        span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                            "you seem to be using .map() to clone the contents of an {}, consider \
                                            using `.cloned()`", type_name),
                                            &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                                    }
                                }
                            }
                        }
                    }
                    ExprPath(_, ref path) => {
                        if match_path(path, &CLONE_PATH) {
                            let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
                            span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
                                "you seem to be using .map() to clone the contents of an {}, consider \
                                using `.cloned()`", type_name),
                                &format!("try\n{}.cloned()", snippet(cx, args[0].span, "..")));
                        }
                    }
                    _ => (),
                }
            }
        }
    }
}

fn expr_eq_ident(expr: &Expr, id: Ident) -> bool {
    match expr.node {
        ExprPath(None, ref path) => {
            let arg_segment = [PathSegment { identifier: id, parameters: PathParameters::none() }];
            !path.global && path.segments[..] == arg_segment
        }
        _ => false,
    }
}

fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
    if match_trait_method(cx, expr, &["core", "iter", "Iterator"]) {
        Some("iterator")
    } else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &OPTION_PATH) {
        Some("Option")
    } else {
        None
    }
}

fn get_arg_name(pat: &Pat) -> Option<Ident> {
    match pat.node {
        PatIdent(_, ident, None) => Some(ident.node),
        PatRegion(ref subpat, _) => get_arg_name(subpat),
        _ => None,
    }
}

fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool {
    match expr.node {
        ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => {
            only_derefs(cx, subexpr, id)
        }
        _ => expr_eq_ident(expr, id),
    }
}

impl LintPass for MapClonePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(MAP_CLONE)
    }
}
<|endoftext|>


<commit_before>use atom::*;
use symbol;

use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug,PartialEq)]
struct EnvGeneration {
    value: Vec<Entry>,
    parent: Option<Env>
}

impl EnvGeneration {
    fn new(parent: Option<Env>) -> EnvGeneration {
        EnvGeneration {
            value: Vec::new(),
            parent: parent
        }
    }
}

#[derive (Debug, Clone, PartialEq)]
struct Entry {
    key: symbol::InternedStr,
    value: Atom
}

#[derive (Debug, Clone, PartialEq)]
pub struct Env(Rc<RefCell<EnvGeneration>>);

impl Env {
    pub fn new(parent: Option<Env>) -> Env {
        Env(Rc::new(RefCell::new(EnvGeneration::new(parent))))
    }

    fn find(&self, key: &str) -> Option<Atom> {
        let gen = self.0.borrow();
        let value = &gen.value;
        match value.iter().find(|entry| entry.key.as_ref() == key) {
            Some(ref entry) => {
                Some(entry.value.clone())
            },
            None => {
                if let Some(ref parent) = gen.parent {
                    parent.find(key)
                } else {
                    None
                }
            }
        }
    }

    pub fn bind(&mut self, params: &[Atom], args: &[Atom]) -> Env {
        let mut arg_map = vec![];
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();

        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.map(|a| a.clone()).collect();
                    arg_map.push(Entry { key: splat.clone(), value: Atom::List(vals) });
                    break;
                }
            } else {
                args_iter.next().map(|arg| {
                    arg_map.push(Entry { key: sym.clone(), value: arg.clone() });
                });
            }
        }

        let env_gen = EnvGeneration {
            value: arg_map,
            parent: Some(self.clone())
        };
        Env(Rc::new(RefCell::new(env_gen)))
    }

    pub fn get(&self, key: &str) -> Option<Atom> {
        self.find(key)
    }

    pub fn set(&mut self, key: symbol::InternedStr, value: Atom) {
        self.0.borrow_mut().value.push(Entry {
            key: key,
            value: value
        });
    }
}

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

    #[test]
    fn nested_get() {
        let mut env = Env::new(None);

        env.set(intern("foo"), Atom::String("bar".to_owned()));

        let env2 = Env::new(Some(env.clone()));

        assert_eq!(Atom::String("bar".to_owned()), env2.get(intern("foo").as_ref()).unwrap());
    }

    #[test]
    fn splat() {
        // let mut env = Env::new(None);

        // let params = vec![Atom::symbol("&"), Atom::symbol("body")];

        // env.apply(&params, &vec![Atom::from(0), Atom::from(1), Atom::from(2)]);

        // let body = env.get("body").unwrap();

        // assert_eq!(Atom::List(vec![Atom::from(0), Atom::from(1), Atom::from(2)]), body);
    }

}
<commit_msg>add this test back<commit_after>use atom::*;
use symbol;

use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug,PartialEq)]
struct EnvGeneration {
    value: Vec<Entry>,
    parent: Option<Env>
}

impl EnvGeneration {
    fn new(parent: Option<Env>) -> EnvGeneration {
        EnvGeneration {
            value: Vec::new(),
            parent: parent
        }
    }
}

#[derive (Debug, Clone, PartialEq)]
struct Entry {
    key: symbol::InternedStr,
    value: Atom
}

#[derive (Debug, Clone, PartialEq)]
pub struct Env(Rc<RefCell<EnvGeneration>>);

impl Env {
    pub fn new(parent: Option<Env>) -> Env {
        Env(Rc::new(RefCell::new(EnvGeneration::new(parent))))
    }

    fn find(&self, key: &str) -> Option<Atom> {
        let gen = self.0.borrow();
        let value = &gen.value;
        match value.iter().find(|entry| entry.key.as_ref() == key) {
            Some(ref entry) => {
                Some(entry.value.clone())
            },
            None => {
                if let Some(ref parent) = gen.parent {
                    parent.find(key)
                } else {
                    None
                }
            }
        }
    }

    pub fn bind(&mut self, params: &[Atom], args: &[Atom]) -> Env {
        let mut arg_map = vec![];
        let mut params_iter = params.iter();
        let mut args_iter = args.iter();

        while let Some(&Atom::Symbol(ref sym)) = params_iter.next() {
            if sym.as_ref() == "&" {
                if let Some(&Atom::Symbol(ref splat)) = params_iter.next() {
                    let vals = args_iter.map(|a| a.clone()).collect();
                    arg_map.push(Entry { key: splat.clone(), value: Atom::List(vals) });
                    break;
                }
            } else {
                args_iter.next().map(|arg| {
                    arg_map.push(Entry { key: sym.clone(), value: arg.clone() });
                });
            }
        }

        let env_gen = EnvGeneration {
            value: arg_map,
            parent: Some(self.clone())
        };
        Env(Rc::new(RefCell::new(env_gen)))
    }

    pub fn get(&self, key: &str) -> Option<Atom> {
        self.find(key)
    }

    pub fn set(&mut self, key: symbol::InternedStr, value: Atom) {
        self.0.borrow_mut().value.push(Entry {
            key: key,
            value: value
        });
    }
}

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

    #[test]
    fn nested_get() {
        let mut env = Env::new(None);

        env.set(intern("foo"), Atom::String("bar".to_owned()));

        let env2 = Env::new(Some(env.clone()));

        assert_eq!(Atom::String("bar".to_owned()), env2.get(intern("foo").as_ref()).unwrap());
    }

    #[test]
    fn splat() {
        let mut env = Env::new(None);

        let params = vec![Atom::symbol("&"), Atom::symbol("body")];

        let e = env.bind(&params, &vec![Atom::from(0), Atom::from(1), Atom::from(2)]);

        let body = e.get("body").unwrap();

        assert_eq!(Atom::List(vec![Atom::from(0), Atom::from(1), Atom::from(2)]), body);
    }

}
<|endoftext|>


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

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
#![cfg_attr(test, feature(rand, rustc_private, test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bit_vec::BitVec;
pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use linked_list::LinkedList;
pub use enum_set::EnumSet;
pub use vec_deque::VecDeque;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
#[unstable(feature = "collections")]
pub use vec_deque as ring_buf;

#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
#[unstable(feature = "collections")]
pub use linked_list as dlist;

#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
#[unstable(feature = "collections")]
pub use bit_vec as bitv;

#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
#[unstable(feature = "collections")]
pub use bit_set as bitv_set;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

#[cfg(test)] #[macro_use] mod bench;

pub mod binary_heap;
mod bit;
mod btree;
pub mod borrow;
pub mod enum_set;
pub mod fmt;
pub mod linked_list;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_deque;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_vec {
    pub use bit::{BitVec, Iter};

    #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
    #[unstable(feature = "collections")]
    pub use bit::BitVec as Bitv;
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_set {
    pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;

    #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
    #[unstable(feature = "collections")]
    pub use bit::BitSet as BitvSet;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use borrow::IntoCow;
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<commit_msg>Auto merge of #23256 - apasel422:bound, r=alexcrichton<commit_after>// Copyright 2013-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.

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag)]
#![cfg_attr(test, feature(rand, rustc_private, test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bit_vec::BitVec;
pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use linked_list::LinkedList;
pub use enum_set::EnumSet;
pub use vec_deque::VecDeque;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
#[unstable(feature = "collections")]
pub use vec_deque as ring_buf;

#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
#[unstable(feature = "collections")]
pub use linked_list as dlist;

#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
#[unstable(feature = "collections")]
pub use bit_vec as bitv;

#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
#[unstable(feature = "collections")]
pub use bit_set as bitv_set;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

#[cfg(test)] #[macro_use] mod bench;

pub mod binary_heap;
mod bit;
mod btree;
pub mod borrow;
pub mod enum_set;
pub mod fmt;
pub mod linked_list;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_deque;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_vec {
    pub use bit::{BitVec, Iter};

    #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
    #[unstable(feature = "collections")]
    pub use bit::BitVec as Bitv;
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bit_set {
    pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;

    #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
    #[unstable(feature = "collections")]
    pub use bit::BitSet as BitvSet;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use borrow::IntoCow;
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<|endoftext|>