<commit_before>//! Handles CPU startup (segment init, etc) that's common to all CPUs.
//! Chip specific init (like the interrupt table) should be in the relevant <chip> module.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use r0;
use cortex_m;
use alloc_cortex_m;

use board;
// use cpu::{systick, uart};

extern "C" {
    // These symbols come from the linker script
    static mut _data_start_flash: usize;
    static mut _data_start: usize;
    static mut _data_end: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    static mut _heap_start: usize;
    static mut _heap_end: usize;
    // This is defined by your application
    fn main();
    fn _stack_top();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// Contains exception handlers, interrupt service routine vectors and a magic value
/// that marks the start of the stack.
#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<cortex_m::Handler>; 48] = [// Stack pointer
                                                           Some(_stack_top),
                                                           // Reset
                                                           Some(reset_vector),
                                                           // NMI
                                                           Some(isr_nmi),
                                                           // Hard Fault
                                                           Some(isr_hardfault),
                                                           // Unused
                                                           None,
                                                           // CM0+ Bus Fault
                                                           Some(isr_busfault),
                                                           // CM0+ Usage Fault
                                                           Some(isr_usagefault),
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Supervisor call
                                                           Some(isr_svcall),
                                                           // Debug monitor
                                                           Some(isr_debugmon),
                                                           // Unused
                                                           None,
                                                           // Pendable service request
                                                           Some(isr_pendsv),
                                                           // SysTick
                                                           Some(isr_systick),
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // MCM
                                                           None,
                                                           // Flash
                                                           None,
                                                           // PMC
                                                           None,
                                                           // LLWU
                                                           None,
                                                           // I2C0
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // SPI0
                                                           None,
                                                           // SPI1
                                                           None,
                                                           // SCI0
                                                           None,
                                                           // SCI1
                                                           None,
                                                           // SCI2
                                                           None,
                                                           // ADC0
                                                           None,
                                                           // ACMP0
                                                           None,
                                                           // FTM0
                                                           None,
                                                           // FTM1
                                                           None,
                                                           // FTM2
                                                           None,
                                                           // RTC
                                                           None,
                                                           // ACMP1
                                                           None,
                                                           // PIT_CH0
                                                           None,
                                                           // PIT_CH1
                                                           None,
                                                           // KBI0
                                                           None,
                                                           // KBI1
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // ICS
                                                           None,
                                                           // Watchdog
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None];

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

/// Kind of exception
#[derive(Debug)]
enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Performs what you might otherwise call 'C Startup'.
/// This routine is specified at the reset vector in the ISR vector table.
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
pub unsafe extern "C" fn reset_vector() {
    let data_start_flash: *mut usize = &mut _data_start_flash;
    let data_start: *mut usize = &mut _data_start;
    let data_end: *mut usize = &mut _data_end;
    let bss_start: *mut usize = &mut _bss_start;
    let bss_end: *mut usize = &mut _bss_end;
    let heap_start: *mut usize = &mut _heap_start;
    let heap_end: *mut usize = &mut _heap_end;

    r0::init_data(data_start, data_end, data_start_flash);
    r0::zero_bss(bss_start, bss_end);

    alloc_cortex_m::init(heap_start, heap_end);

    // Freescale app does
    // __init_registers
    // __init_hardware
    //   - Sets SCB->VTOR
    // __init_user
    //

    // Need to perform SIM init
    // Then ICS init

    board::init();
    main();
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,
        }
    }
}

/// A HardFault is an exception that occurs because of an error during
/// exception processing, or because an exception cannot be managed by any
/// other exception mechanism. HardFaults have a fixed priority of -1, meaning
/// they have higher priority than any exception with configurable priority.
///
/// This function came from japaric's excellent F3 crate.
#[naked]
pub unsafe extern "C" fn isr_hardfault() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          bl isr_hardfault_rs" :::: "volatile");

    intrinsics::unreachable();
}

/// Once the StacFrame has been gathered by `isr_hardfault`, we can process the
/// HardFault using a normal Rust function. It's `no_mangle` because we
/// refer to it from raw assembler in `isr_hardfault`.
#[no_mangle]
pub unsafe extern "C" fn isr_hardfault_rs(_sf: &cortex_m::StackFrame) -> ! {
    // Need ITM support for this to work
    // iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    // We can see this in the debugger
    let _exc = Exception::current();

    bkpt!();

    loop {}
}

/// A Non Maskable Interrupt (NMI) can be signalled by a peripheral or
/// triggered by software. This is the highest priority exception other than
/// reset. It is permanently enabled and has a fixed priority of -2. NMIs
/// cannot be:
/// * masked or prevented from activation by any other exception
/// * preempted by any exception other than Reset.
pub unsafe extern "C" fn isr_nmi() {
    // Do nothing
}

/// A MemManage fault is an exception that occurs because of a memory
/// protection related fault. The the fixed memory protection constraints
/// determines this fault, for both instruction and data memory transactions.
/// This fault is always used to abort instruction accesses to Execute Never
/// (XN) memory regions.
pub unsafe extern "C" fn isr_mmfault() {
    board::panic();
}

/// A BusFault is an exception that occurs because of a memory related fault
/// for an instruction or data memory transaction. This might be from an error
/// detected on a bus in the memory system.
pub unsafe extern "C" fn isr_busfault() {
    board::panic();
}

/// A UsageFault is an exception that occurs because of a fault related to instruction execution. This includes:
/// * an undefined instruction
/// * an illegal unaligned access
/// * invalid state on instruction execution
/// * an error on exception return.
/// The following can cause a UsageFault when the core is configured to report them:
/// * an unaligned address on word and halfword memory access
/// * division by zero.
pub unsafe extern "C" fn isr_usagefault() {
    board::panic();
}

/// A supervisor call (SVC) is an exception that is triggered by the SVC
/// instruction. In an OS environment, applications can use SVC instructions
/// to access OS kernel functions and device drivers.
pub unsafe extern "C" fn isr_svcall() {
    // Nothing
}

/// Debug monitor interrupt handler.
pub unsafe extern "C" fn isr_debugmon() {
    // Nothing
}

/// PendSV is an interrupt-driven request for system-level service. In an OS
/// environment, use PendSV for context switching when no other exception is
/// active.
pub unsafe extern "C" fn isr_pendsv() {
    // Nothing
}

/// A SysTick exception is an exception the system timer generates when it
/// reaches zero. Software can also generate a SysTick exception. In an OS
/// environment, the processor can use this exception as system tick.
pub unsafe extern "C" fn isr_systick() {
    // systick::isr();
}

/// A place-holder ISR used when we have nothing better to use.
pub unsafe extern "C" fn isr_empty_def() {
    board::panic();
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Don't mangle reset_vector so you can break on it in gdb.<commit_after>//! Handles CPU startup (segment init, etc) that's common to all CPUs.
//! Chip specific init (like the interrupt table) should be in the relevant <chip> module.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use r0;
use cortex_m;
use alloc_cortex_m;

use board;
// use cpu::{systick, uart};

extern "C" {
    // These symbols come from the linker script
    static mut _data_start_flash: usize;
    static mut _data_start: usize;
    static mut _data_end: usize;
    static mut _bss_start: usize;
    static mut _bss_end: usize;
    static mut _heap_start: usize;
    static mut _heap_end: usize;
    // This is defined by your application
    fn main();
    fn _stack_top();
}

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

/// Contains exception handlers, interrupt service routine vectors and a magic value
/// that marks the start of the stack.
#[link_section=".nvic_table"]
#[no_mangle]
pub static ISR_VECTORS: [Option<cortex_m::Handler>; 48] = [// Stack pointer
                                                           Some(_stack_top),
                                                           // Reset
                                                           Some(reset_vector),
                                                           // NMI
                                                           Some(isr_nmi),
                                                           // Hard Fault
                                                           Some(isr_hardfault),
                                                           // Unused
                                                           None,
                                                           // CM0+ Bus Fault
                                                           Some(isr_busfault),
                                                           // CM0+ Usage Fault
                                                           Some(isr_usagefault),
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Unused
                                                           None,
                                                           // Supervisor call
                                                           Some(isr_svcall),
                                                           // Debug monitor
                                                           Some(isr_debugmon),
                                                           // Unused
                                                           None,
                                                           // Pendable service request
                                                           Some(isr_pendsv),
                                                           // SysTick
                                                           Some(isr_systick),
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // DMA Channel 0 transfer complete
                                                           None,
                                                           // MCM
                                                           None,
                                                           // Flash
                                                           None,
                                                           // PMC
                                                           None,
                                                           // LLWU
                                                           None,
                                                           // I2C0
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // SPI0
                                                           None,
                                                           // SPI1
                                                           None,
                                                           // SCI0
                                                           None,
                                                           // SCI1
                                                           None,
                                                           // SCI2
                                                           None,
                                                           // ADC0
                                                           None,
                                                           // ACMP0
                                                           None,
                                                           // FTM0
                                                           None,
                                                           // FTM1
                                                           None,
                                                           // FTM2
                                                           None,
                                                           // RTC
                                                           None,
                                                           // ACMP1
                                                           None,
                                                           // PIT_CH0
                                                           None,
                                                           // PIT_CH1
                                                           None,
                                                           // KBI0
                                                           None,
                                                           // KBI1
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // ICS
                                                           None,
                                                           // Watchdog
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None,
                                                           // Reserved
                                                           None];

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

/// Kind of exception
#[derive(Debug)]
enum Exception {
    /// i.e. currently not servicing an exception
    ThreadMode,
    /// Non-maskable interrupt.
    Nmi,
    /// All class of fault.
    HardFault,
    /// Memory management.
    MemoryManagementFault,
    /// Pre-fetch fault, memory access fault.
    BusFault,
    /// Undefined instruction or illegal state.
    UsageFault,
    /// System service call via SWI instruction
    SVCall,
    /// Pendable request for system service
    PendSV,
    /// System tick timer
    Systick,
    /// An interrupt
    Interrupt(u8),
    // Unreachable variant
    #[doc(hidden)]
    Reserved,
}

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

/// Performs what you might otherwise call 'C Startup'.
/// This routine is specified at the reset vector in the ISR vector table.
///
/// Copies global .data init from flash to SRAM and then
/// zeros the bss segment.
#[no_mangle]
pub unsafe extern "C" fn reset_vector() {
    let data_start_flash: *mut usize = &mut _data_start_flash;
    let data_start: *mut usize = &mut _data_start;
    let data_end: *mut usize = &mut _data_end;
    let bss_start: *mut usize = &mut _bss_start;
    let bss_end: *mut usize = &mut _bss_end;
    let heap_start: *mut usize = &mut _heap_start;
    let heap_end: *mut usize = &mut _heap_end;

    r0::init_data(data_start, data_end, data_start_flash);
    r0::zero_bss(bss_start, bss_end);

    alloc_cortex_m::init(heap_start, heap_end);

    // Freescale app does
    // __init_registers
    // __init_hardware
    //   - Sets SCB->VTOR
    // __init_user
    //

    // Need to perform SIM init
    // Then ICS init

    board::init();
    main();
    loop {}
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

impl Exception {
    /// Returns the exception that's currently being serviced
    pub fn current() -> Exception {
        match cortex_m::peripheral::scb().icsr.read() as u8 {
            0 => Exception::ThreadMode,
            2 => Exception::Nmi,
            3 => Exception::HardFault,
            4 => Exception::MemoryManagementFault,
            5 => Exception::BusFault,
            6 => Exception::UsageFault,
            11 => Exception::SVCall,
            14 => Exception::PendSV,
            15 => Exception::Systick,
            n if n >= 16 => Exception::Interrupt(n - 16),
            _ => Exception::Reserved,
        }
    }
}

/// A HardFault is an exception that occurs because of an error during
/// exception processing, or because an exception cannot be managed by any
/// other exception mechanism. HardFaults have a fixed priority of -1, meaning
/// they have higher priority than any exception with configurable priority.
///
/// This function came from japaric's excellent F3 crate.
#[naked]
pub unsafe extern "C" fn isr_hardfault() {
    use core::intrinsics;

    // NOTE need asm!, #[naked] and unreachable() to avoid modifying the stack
    // pointer (MSP)
    asm!("mrs r0, MSP
          ldr r1, [r0, #20]
          bl isr_hardfault_rs" :::: "volatile");

    intrinsics::unreachable();
}

/// Once the StacFrame has been gathered by `isr_hardfault`, we can process the
/// HardFault using a normal Rust function. It's `no_mangle` because we
/// refer to it from raw assembler in `isr_hardfault`.
#[no_mangle]
pub unsafe extern "C" fn isr_hardfault_rs(_sf: &cortex_m::StackFrame) -> ! {
    // Need ITM support for this to work
    // iprintln!("EXCEPTION {:?} @ PC=0x{:08x}", Exception::current(), sf.pc);

    // We can see this in the debugger
    let _exc = Exception::current();

    bkpt!();

    loop {}
}

/// A Non Maskable Interrupt (NMI) can be signalled by a peripheral or
/// triggered by software. This is the highest priority exception other than
/// reset. It is permanently enabled and has a fixed priority of -2. NMIs
/// cannot be:
/// * masked or prevented from activation by any other exception
/// * preempted by any exception other than Reset.
pub unsafe extern "C" fn isr_nmi() {
    // Do nothing
}

/// A MemManage fault is an exception that occurs because of a memory
/// protection related fault. The the fixed memory protection constraints
/// determines this fault, for both instruction and data memory transactions.
/// This fault is always used to abort instruction accesses to Execute Never
/// (XN) memory regions.
pub unsafe extern "C" fn isr_mmfault() {
    board::panic();
}

/// A BusFault is an exception that occurs because of a memory related fault
/// for an instruction or data memory transaction. This might be from an error
/// detected on a bus in the memory system.
pub unsafe extern "C" fn isr_busfault() {
    board::panic();
}

/// A UsageFault is an exception that occurs because of a fault related to instruction execution. This includes:
/// * an undefined instruction
/// * an illegal unaligned access
/// * invalid state on instruction execution
/// * an error on exception return.
/// The following can cause a UsageFault when the core is configured to report them:
/// * an unaligned address on word and halfword memory access
/// * division by zero.
pub unsafe extern "C" fn isr_usagefault() {
    board::panic();
}

/// A supervisor call (SVC) is an exception that is triggered by the SVC
/// instruction. In an OS environment, applications can use SVC instructions
/// to access OS kernel functions and device drivers.
pub unsafe extern "C" fn isr_svcall() {
    // Nothing
}

/// Debug monitor interrupt handler.
pub unsafe extern "C" fn isr_debugmon() {
    // Nothing
}

/// PendSV is an interrupt-driven request for system-level service. In an OS
/// environment, use PendSV for context switching when no other exception is
/// active.
pub unsafe extern "C" fn isr_pendsv() {
    // Nothing
}

/// A SysTick exception is an exception the system timer generates when it
/// reaches zero. Software can also generate a SysTick exception. In an OS
/// environment, the processor can use this exception as system tick.
pub unsafe extern "C" fn isr_systick() {
    // systick::isr();
}

/// A place-holder ISR used when we have nothing better to use.
pub unsafe extern "C" fn isr_empty_def() {
    board::panic();
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>use super::super::{Y, X, Coord, Grid};
use super::*;

pub struct Field {
    size: i32,
    n_alpha: i32,
    cand: Grid<Cand>,
    value: Grid<Value>,
    clue_front: Vec<Clue>,
    clue_back: Vec<Clue>,
    inconsistent: bool,
    solved: bool,
}

impl Field {
    pub fn empty_board(size: i32, n_alpha: i32) -> Field {
        assert!(n_alpha >= 2);
        Field {
            size,
            n_alpha,
            cand: Grid::new(size, size, Cand((1u32 << n_alpha) - 1)),
            value: Grid::new(size, size, UNDECIDED),
            clue_front: vec![NO_CLUE; (2 * size) as usize],
            clue_back: vec![NO_CLUE; (2 * size) as usize],
            inconsistent: false,
            solved: false,
        }
    }
    pub fn get_value(&self, cell: Coord) -> Value {
        self.value[cell]
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn get_clue(&self, loc: ClueLoc, idx: i32) -> Clue {
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize],
            ClueLoc::Right => self.clue_back[idx as usize],
            ClueLoc::Top => self.clue_front[(idx + self.size) as usize],
            ClueLoc::Bottom => self.clue_back[(idx + self.size) as usize],
        }
    }
    pub fn set_clue(&mut self, loc: ClueLoc, idx: i32, clue: Clue) {
        let current = self.get_clue(loc, idx);
        if current != NO_CLUE {
            if current != clue {
                self.inconsistent = true;
            }
            return;
        }
        let size = self.size;
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize] = clue,
            ClueLoc::Right => self.clue_back[idx as usize] = clue,
            ClueLoc::Top => self.clue_front[(idx + size) as usize] = clue,
            ClueLoc::Bottom => self.clue_back[(idx + size) as usize] = clue,
        }
        if loc == ClueLoc::Left || loc == ClueLoc::Right {
            self.inspect_row(idx);
        } else {
            self.inspect_row(idx + size);
        }
    }
    pub fn decide(&mut self, cell: Coord, val: Value) {
        let current = self.value[cell];
        if current != UNDECIDED && !(current == SOME && val != EMPTY) {
            if current != val {
                self.inconsistent = true;
            }
            return;
        }

        self.value[cell] = val;

        if val == EMPTY {
            self.limit_cand(cell, Cand(0));
        } else if val == SOME {
            self.inspect_cell(cell);
        } else if val != UNDECIDED {
            self.limit_cand(cell, Cand::singleton(val.0));

            let (Y(y), X(x)) = cell;
            let limit = !Cand::singleton(val.0);
            for y2 in 0..self.size {
                if y != y2 { self.limit_cand((Y(y2), X(x)), limit); }
            }
            for x2 in 0..self.size {
                if x != x2 { self.limit_cand((Y(y), X(x2)), limit); }
            }
        }
    }
    /// Returns `pos`-th cell of group `gid`.
    fn group(&self, gid: i32, pos: i32) -> Coord {
        if gid < self.size {
            (Y(gid), X(pos))
        } else {
            (Y(pos), X(gid - self.size))
        }
    }
    /// Returns `pos`-th cell of group `gid` with reversed indexing of cells when `dir` is `true`.
    fn directed_group(&self, gid: i32, pos: i32, dir: bool) -> Coord {
        self.group(gid, if dir { self.size - pos - 1 } else { pos })
    }
    fn limit_cand(&mut self, cell: Coord, lim: Cand) {
        let current_cand = self.cand[cell];

        if (current_cand & lim) == current_cand {
            return;
        }

        let new_cand = current_cand & lim;
        self.cand[cell] = new_cand;

        if self.cand[cell] == Cand(0) {
            self.decide(cell, EMPTY);
        }
        self.inspect_cell(cell);
    }
    fn inspect_cell(&mut self, cell: Coord) {
        if self.value[cell] == SOME && self.cand[cell].count_set_cands() == 1 {
            let val = Value(self.cand[cell].smallest_set_cand());
            self.decide(cell, val);
        }
        let size = self.size;
        let (Y(y), X(x)) = cell;
        self.inspect_row(y);
        self.inspect_row(x + size);
    }
    fn inspect_row(&mut self, group: i32) {
        let size = self.size;
        let n_alpha = self.n_alpha;

        let mut n_some = 0;
        let mut n_empty = 0;

        for i in 0..size {
            let v = self.value[self.group(group, i)];
            if v == EMPTY {
                n_empty += 1;
            } else if v != UNDECIDED {
                n_some += 1;
            }
        }

        if n_some == n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, EMPTY);
                }
            }
        }
        if n_empty == size - n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, SOME);
                }
            }
        }

        for a in 0..n_alpha {
            let mut loc = -1;
            for i in 0..size {
                if self.cand[self.group(group, i)].is_set(a) {
                    if loc == -1 {
                        loc = i;
                    } else {
                        loc = -2;
                        break;
                    }
                }
            }
            if loc == -1 {
                self.inconsistent = true;
                return;
            } else if loc != -2 {
                let c = self.group(group, loc);
                self.decide(c, Value(a));
            }
        }
        for &dir in [true, false].iter() {
            let clue = if !dir { self.clue_front[group as usize] } else { self.clue_back[group as usize] };
            if clue == NO_CLUE {
                continue;
            }

            let mut first_nonempty_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v != EMPTY {
                    first_nonempty_id = i;
                    break;
                }
            }
            if first_nonempty_id == -1 {
                self.inconsistent = true;
                return;
            }
            let first_nonempty_cell = self.directed_group(group, first_nonempty_id, dir);
            self.limit_cand(first_nonempty_cell, Cand::singleton(clue.0));

            let mut first_diff_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v == SOME && !self.cand[self.directed_group(group, i, dir)].is_set(clue.0) {
                    first_diff_id = i;
                }
            }
            if first_diff_id != -1 {
                for i in (first_diff_id + 1)..size {
                    let c = self.directed_group(group, i, dir);
                    self.limit_cand(c, !Cand::singleton(clue.0));
                }
            }

            let mut n_back_diff = n_alpha - 1;
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                let v = self.value[c];
                if v != EMPTY {
                    self.limit_cand(c, !Cand::singleton(clue.0));
                    n_back_diff -= 1;
                    if n_back_diff == 0 { break; }
                }
            }

            let mut mask = Cand((1u32 << n_alpha) - 1) & !Cand::singleton(clue.0);
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                self.limit_cand(c, !Cand::singleton(clue.0));
                mask &= !self.cand[c];
                if mask == Cand(0) {
                    break;
                }
            }
        }
    }
    /// Apply *fishy method* (like *X-wing* and *Sword fish* in Sudoku) to the field.
    /// Note: runs in O*(2^size) and works only if size < 32.
    pub fn fishy_method(&mut self) {
        let size = self.size;
        for i in 0..self.n_alpha {
            let mut masks = vec![];
            for y in 0..size {
                let mut mask = 0u32;
                for x in 0..size {
                    if self.cand[(Y(y), X(x))].is_set(i) {
                        mask |= 1u32 << x;
                    }
                }
                masks.push(mask);
            }
            for bits in 1..(1u32 << size) {
                let mut ors = 0u32;
                for y in 0..size {
                    if (bits & (1u32 << y)) != 0 {
                        ors |= masks[y as usize];
                    }
                }
                if bits.count_ones() > ors.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if bits.count_ones() == ors.count_ones() {
                    for y in 0..size {
                        if (bits & (1u32 << y)) == 0 {
                            masks[y as usize] &= !ors;
                        }
                    }
                }
            }
            for y in 0..size {
                for x in 0..size {
                    if (masks[y as usize] & (1u32 << x)) == 0 {
                        self.limit_cand((Y(y), X(x)), !Cand::singleton(i));
                    }
                }
            }
        }
    }
}

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

    #[test]
    fn test_deduction() {
        {
            // a symbol shouldn't occur more than once in a row / a column
            let mut field = Field::empty_board(5, 3);

            assert_eq!(field.cand[(Y(0), X(0))], Cand(7));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(7));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));

            field.decide((Y(0), X(0)), Value(0));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(0))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::empty_board(5, 3);

            field.decide((Y(1), X(0)), SOME);
            field.decide((Y(1), X(1)), SOME);
            field.decide((Y(1), X(2)), SOME);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(3))], EMPTY);
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::empty_board(5, 3);

            field.decide((Y(3), X(2)), EMPTY);
            field.decide((Y(4), X(2)), EMPTY);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], SOME);
        }
        {
            let mut field = Field::empty_board(5, 3);

            field.limit_cand((Y(0), X(2)), Cand(5));
            field.limit_cand((Y(2), X(2)), Cand(5));
            field.limit_cand((Y(3), X(2)), Cand(5));
            field.limit_cand((Y(4), X(2)), Cand(5));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], Value(1));
            assert_eq!(field.cand[(Y(1), X(3))], Cand(5));
        }
    }

    #[test]
    fn test_clue() {
        {
            let mut field = Field::empty_board(5, 3);

            field.set_clue(ClueLoc::Left, 0, Clue(0));

            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(3))], Cand(6));
            assert_eq!(field.cand[(Y(0), X(4))], Cand(6));
        }
    }
}
<commit_msg>Endview: add hidden candidate technique to Field<commit_after>use super::super::{Y, X, Coord, Grid};
use super::*;

pub struct Field {
    size: i32,
    n_alpha: i32,
    cand: Grid<Cand>,
    value: Grid<Value>,
    clue_front: Vec<Clue>,
    clue_back: Vec<Clue>,
    inconsistent: bool,
    solved: bool,
}

impl Field {
    pub fn empty_board(size: i32, n_alpha: i32) -> Field {
        assert!(n_alpha >= 2);
        Field {
            size,
            n_alpha,
            cand: Grid::new(size, size, Cand((1u32 << n_alpha) - 1)),
            value: Grid::new(size, size, UNDECIDED),
            clue_front: vec![NO_CLUE; (2 * size) as usize],
            clue_back: vec![NO_CLUE; (2 * size) as usize],
            inconsistent: false,
            solved: false,
        }
    }
    pub fn get_value(&self, cell: Coord) -> Value {
        self.value[cell]
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn get_clue(&self, loc: ClueLoc, idx: i32) -> Clue {
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize],
            ClueLoc::Right => self.clue_back[idx as usize],
            ClueLoc::Top => self.clue_front[(idx + self.size) as usize],
            ClueLoc::Bottom => self.clue_back[(idx + self.size) as usize],
        }
    }
    pub fn set_clue(&mut self, loc: ClueLoc, idx: i32, clue: Clue) {
        let current = self.get_clue(loc, idx);
        if current != NO_CLUE {
            if current != clue {
                self.inconsistent = true;
            }
            return;
        }
        let size = self.size;
        match loc {
            ClueLoc::Left => self.clue_front[idx as usize] = clue,
            ClueLoc::Right => self.clue_back[idx as usize] = clue,
            ClueLoc::Top => self.clue_front[(idx + size) as usize] = clue,
            ClueLoc::Bottom => self.clue_back[(idx + size) as usize] = clue,
        }
        if loc == ClueLoc::Left || loc == ClueLoc::Right {
            self.inspect_row(idx);
        } else {
            self.inspect_row(idx + size);
        }
    }
    pub fn decide(&mut self, cell: Coord, val: Value) {
        let current = self.value[cell];
        if current.0 >= 0 && val == SOME {
            return;
        }
        if current != UNDECIDED && !(current == SOME && val != EMPTY) {
            if current != val {
                self.inconsistent = true;
            }
            return;
        }

        self.value[cell] = val;

        if val == EMPTY {
            self.limit_cand(cell, Cand(0));
        } else if val == SOME {
            self.inspect_cell(cell);
        } else if val != UNDECIDED {
            self.limit_cand(cell, Cand::singleton(val.0));

            let (Y(y), X(x)) = cell;
            let limit = !Cand::singleton(val.0);
            for y2 in 0..self.size {
                if y != y2 { self.limit_cand((Y(y2), X(x)), limit); }
            }
            for x2 in 0..self.size {
                if x != x2 { self.limit_cand((Y(y), X(x2)), limit); }
            }
        }
    }
    /// Returns `pos`-th cell of group `gid`.
    fn group(&self, gid: i32, pos: i32) -> Coord {
        if gid < self.size {
            (Y(gid), X(pos))
        } else {
            (Y(pos), X(gid - self.size))
        }
    }
    /// Returns `pos`-th cell of group `gid` with reversed indexing of cells when `dir` is `true`.
    fn directed_group(&self, gid: i32, pos: i32, dir: bool) -> Coord {
        self.group(gid, if dir { self.size - pos - 1 } else { pos })
    }
    fn limit_cand(&mut self, cell: Coord, lim: Cand) {
        let current_cand = self.cand[cell];

        if (current_cand & lim) == current_cand {
            return;
        }

        let new_cand = current_cand & lim;
        self.cand[cell] = new_cand;

        if self.cand[cell] == Cand(0) {
            self.decide(cell, EMPTY);
        }
        self.inspect_cell(cell);
    }
    fn inspect_cell(&mut self, cell: Coord) {
        if self.value[cell] == SOME && self.cand[cell].count_set_cands() == 1 {
            let val = Value(self.cand[cell].smallest_set_cand());
            self.decide(cell, val);
        }
        let size = self.size;
        let (Y(y), X(x)) = cell;
        self.inspect_row(y);
        self.inspect_row(x + size);
    }
    fn inspect_row(&mut self, group: i32) {
        let size = self.size;
        let n_alpha = self.n_alpha;

        let mut n_some = 0;
        let mut n_empty = 0;

        for i in 0..size {
            let v = self.value[self.group(group, i)];
            if v == EMPTY {
                n_empty += 1;
            } else if v != UNDECIDED {
                n_some += 1;
            }
        }

        if n_some == n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, EMPTY);
                }
            }
        }
        if n_empty == size - n_alpha {
            for i in 0..size {
                let c = self.group(group, i);
                if self.value[c] == UNDECIDED {
                    self.decide(c, SOME);
                }
            }
        }

        for a in 0..n_alpha {
            let mut loc = -1;
            for i in 0..size {
                if self.cand[self.group(group, i)].is_set(a) {
                    if loc == -1 {
                        loc = i;
                    } else {
                        loc = -2;
                        break;
                    }
                }
            }
            if loc == -1 {
                self.inconsistent = true;
                return;
            } else if loc != -2 {
                let c = self.group(group, loc);
                self.decide(c, Value(a));
            }
        }
        for &dir in [true, false].iter() {
            let clue = if !dir { self.clue_front[group as usize] } else { self.clue_back[group as usize] };
            if clue == NO_CLUE {
                continue;
            }

            let mut first_nonempty_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v != EMPTY {
                    first_nonempty_id = i;
                    break;
                }
            }
            if first_nonempty_id == -1 {
                self.inconsistent = true;
                return;
            }
            let first_nonempty_cell = self.directed_group(group, first_nonempty_id, dir);
            self.limit_cand(first_nonempty_cell, Cand::singleton(clue.0));

            let mut first_diff_id = -1;
            for i in 0..size {
                let v = self.value[self.directed_group(group, i, dir)];
                if v == SOME && !self.cand[self.directed_group(group, i, dir)].is_set(clue.0) {
                    first_diff_id = i;
                }
            }
            if first_diff_id != -1 {
                for i in (first_diff_id + 1)..size {
                    let c = self.directed_group(group, i, dir);
                    self.limit_cand(c, !Cand::singleton(clue.0));
                }
            }

            let mut n_back_diff = n_alpha - 1;
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                let v = self.value[c];
                if v != EMPTY {
                    self.limit_cand(c, !Cand::singleton(clue.0));
                    n_back_diff -= 1;
                    if n_back_diff == 0 { break; }
                }
            }

            let mut mask = Cand((1u32 << n_alpha) - 1) & !Cand::singleton(clue.0);
            for i in 0..size {
                let c = self.directed_group(group, i, !dir);
                self.limit_cand(c, !Cand::singleton(clue.0));
                mask &= !self.cand[c];
                if mask == Cand(0) {
                    break;
                }
            }
        }
    }
    /// Apply *hidden candidate method* to the field.
    /// Note: runs in O*(2^(n_alpha)) and works only if n_alpha < 32.
    pub fn hidden_candidate(&mut self) {
        let size = self.size;
        let n_alpha = self.n_alpha;
        for bits in 1..(1u32 << n_alpha) {
            let mask = Cand(bits);
            for g in 0..(2 * size) {
                let mut n_match = 0;
                for i in 0..size {
                    if self.cand[self.group(g, i)] & mask != Cand(0) {
                        n_match += 1;
                    }
                }
                if n_match < bits.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if n_match == bits.count_ones() {
                    for i in 0..size {
                        let c = self.group(g, i);
                        if self.cand[c] & mask != Cand(0) {
                            self.decide(c, SOME);
                            self.limit_cand(c, mask);
                        }
                    }
                }
            }
        }
    }
    /// Apply *fishy method* (like *X-wing* and *Sword fish* in Sudoku) to the field.
    /// Note: runs in O*(2^size) and works only if size < 32.
    pub fn fishy_method(&mut self) {
        let size = self.size;
        for i in 0..self.n_alpha {
            let mut masks = vec![];
            for y in 0..size {
                let mut mask = 0u32;
                for x in 0..size {
                    if self.cand[(Y(y), X(x))].is_set(i) {
                        mask |= 1u32 << x;
                    }
                }
                masks.push(mask);
            }
            for bits in 1..(1u32 << size) {
                let mut ors = 0u32;
                for y in 0..size {
                    if (bits & (1u32 << y)) != 0 {
                        ors |= masks[y as usize];
                    }
                }
                if bits.count_ones() > ors.count_ones() {
                    self.inconsistent = true;
                    return;
                } else if bits.count_ones() == ors.count_ones() {
                    for y in 0..size {
                        if (bits & (1u32 << y)) == 0 {
                            masks[y as usize] &= !ors;
                        }
                    }
                }
            }
            for y in 0..size {
                for x in 0..size {
                    if (masks[y as usize] & (1u32 << x)) == 0 {
                        self.limit_cand((Y(y), X(x)), !Cand::singleton(i));
                    }
                }
            }
        }
    }
}

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

    #[test]
    fn test_deduction() {
        {
            // a symbol shouldn't occur more than once in a row / a column
            let mut field = Field::empty_board(5, 3);

            assert_eq!(field.cand[(Y(0), X(0))], Cand(7));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(7));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));

            field.decide((Y(0), X(0)), Value(0));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(1))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(0))], Cand(6));
            assert_eq!(field.cand[(Y(1), X(1))], Cand(7));
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::empty_board(5, 3);

            field.decide((Y(1), X(0)), SOME);
            field.decide((Y(1), X(1)), SOME);
            field.decide((Y(1), X(2)), SOME);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(3))], EMPTY);
        }
        {
            // there must be exactly `n_alpha` symbols in a row / a column
            let mut field = Field::empty_board(5, 3);

            field.decide((Y(3), X(2)), EMPTY);
            field.decide((Y(4), X(2)), EMPTY);

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], SOME);
        }
        {
            let mut field = Field::empty_board(5, 3);

            field.limit_cand((Y(0), X(2)), Cand(5));
            field.limit_cand((Y(2), X(2)), Cand(5));
            field.limit_cand((Y(3), X(2)), Cand(5));
            field.limit_cand((Y(4), X(2)), Cand(5));

            assert_eq!(field.inconsistent, false);
            assert_eq!(field.value[(Y(1), X(2))], Value(1));
            assert_eq!(field.cand[(Y(1), X(3))], Cand(5));
        }
    }

    #[test]
    fn test_clue() {
        {
            let mut field = Field::empty_board(5, 3);

            field.set_clue(ClueLoc::Left, 0, Clue(0));

            assert_eq!(field.cand[(Y(0), X(0))], Cand(1));
            assert_eq!(field.cand[(Y(0), X(3))], Cand(6));
            assert_eq!(field.cand[(Y(0), X(4))], Cand(6));
        }
    }
}
<|endoftext|>


<commit_before>//! Playing a music file with SDL2 mixer.

extern crate shader_version;
extern crate event;
extern crate sdl2_window;
extern crate sdl2_mixer;
extern crate sdl2;

use sdl2_window::Sdl2Window;
use sdl2_mixer as mix;
use event::{
    EventIterator,
    EventSettings,
    WindowSettings,
};

fn init_audio() {
    sdl2::init(sdl2::INIT_AUDIO | sdl2::INIT_TIMER);
    // Load dynamic libraries.
    mix::init(
          mix::INIT_MP3
        | mix::INIT_FLAC
        | mix::INIT_MOD
        | mix::INIT_FLUIDSYNTH
        | mix::INIT_MODPLUG
        | mix::INIT_OGG
    );
    mix::open_audio(
        mix::DEFAULT_FREQUENCY,
        mix::DEFAULT_FORMAT,
        mix::DEFAULT_CHANNELS,
        1024
    ).unwrap();
    mix::allocate_channels(mix::DEFAULT_CHANNELS);
}

fn main() {
    let mut window = Sdl2Window::new(
        shader_version::opengl::OpenGL_3_2,
        WindowSettings {
            title: "Music".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    init_audio();

    // Load music file.
    let file = Path::new("./bin/assets/piano.wav");
    let music = mix::Music::from_file(&file).unwrap();

    // Loop once.
    music.play(4).unwrap();

    let event_settings = EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    for _e in EventIterator::new(&mut window, &event_settings) {}
}

<commit_msg>Fix comment in music example<commit_after>//! Playing a music file with SDL2 mixer.

extern crate shader_version;
extern crate event;
extern crate sdl2_window;
extern crate sdl2_mixer;
extern crate sdl2;

use sdl2_window::Sdl2Window;
use sdl2_mixer as mix;
use event::{
    EventIterator,
    EventSettings,
    WindowSettings,
};

fn init_audio() {
    sdl2::init(sdl2::INIT_AUDIO | sdl2::INIT_TIMER);
    // Load dynamic libraries.
    mix::init(
          mix::INIT_MP3
        | mix::INIT_FLAC
        | mix::INIT_MOD
        | mix::INIT_FLUIDSYNTH
        | mix::INIT_MODPLUG
        | mix::INIT_OGG
    );
    mix::open_audio(
        mix::DEFAULT_FREQUENCY,
        mix::DEFAULT_FORMAT,
        mix::DEFAULT_CHANNELS,
        1024
    ).unwrap();
    mix::allocate_channels(mix::DEFAULT_CHANNELS);
}

fn main() {
    let mut window = Sdl2Window::new(
        shader_version::opengl::OpenGL_3_2,
        WindowSettings {
            title: "Music".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    init_audio();

    // Load music file.
    let file = Path::new("./bin/assets/piano.wav");
    let music = mix::Music::from_file(&file).unwrap();

    // Loop four times.
    music.play(4).unwrap();

    let event_settings = EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    for _e in EventIterator::new(&mut window, &event_settings) {}
}

<|endoftext|>


<commit_before>use crate::convert::{Convert};
use std::hash::{Hasher};
use const_random::const_random;

//This file contains the fallback hasher separated so it can be tested independently.
//Nothing here is exported.

//This value is pulled from a 64 bit LCG.
const MULTIPLE: u64 = 6364136223846793005;

const DEFAULT_KEYS: [u64; 2] = [const_random!(u64), const_random!(u64)];

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [AHasher] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    key: u64,
}

/// Provides a [Hasher] is typically used (e.g. by [HashMap]) to create
/// [AHasher]s for each key such that they are hashed independently of one
/// another, since [AHasher]s contain state.
///
/// Constructs a new [AHasher] with compile time generated constants keys.
/// So the key will be the same from one instance to another,
/// but different from build to the next. So if it is possible for a potential
/// attacker to have access to your compiled binary it would be better
/// to specify keys generated at runtime.
///
/// # Examples
///
/// ```
/// use ahash::AHasher;
/// use std::hash::Hasher;
///
/// let mut hasher_1 = AHasher::default();
/// let mut hasher_2 = AHasher::default();
///
/// hasher_1.write_u32(8128);
/// hasher_2.write_u32(8128);
///
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
/// ```
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {
    #[inline]
    fn default() -> AHasher {
        AHasher {buffer: DEFAULT_KEYS[0], key: DEFAULT_KEYS[1]}
    }
}
impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> AHasher {
        AHasher { buffer: key0, key: key1 }
    }
}

#[inline(always)]
fn hash(data: u64, key: u64) -> u64 {
    return (data.wrapping_mul(MULTIPLE).rotate_left(17) ^ key).wrapping_mul(MULTIPLE)
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.buffer = hash(self.buffer ^ i as u64, self.key);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.buffer = hash(self.buffer ^ i as u64, self.key);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.buffer = hash(self.buffer ^ i as u64, self.key);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = hash(self.buffer ^ i, self.key);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let data: [u64;2] = i.convert();
        self.buffer = hash(self.buffer ^ data[0], self.key);
        self.buffer = hash(self.buffer ^ data[1], self.key);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        while data.len() >= 8 {
            let (block, rest) = data.split_at(8);
            let val: u64 = as_array!(block, 8).convert();
            self.buffer = hash(self.buffer ^ val, self.key);
            data = rest;
        }
        if data.len() >= 4 {
            let (block, rest) = data.split_at(4);
            let val: u32 = as_array!(block, 4).convert();
            self.buffer ^= val as u64;
            self.buffer = self.buffer.rotate_left(32);
            data = rest;
        }
        if data.len() >= 2 {
            let (block, rest) = data.split_at(2);
            let val: u16 = as_array!(block, 2).convert();
            self.buffer ^= val as u64;
            self.buffer = self.buffer.rotate_left(16);
            data = rest;
        }
        if data.len() >= 1 {
            self.buffer ^= data[0] as u64;
            self.buffer = self.buffer.rotate_left(8);
        }
        self.buffer = hash(self.buffer ^ length, self.key);
    }
    #[inline]
    fn finish(&self) -> u64 {
        hash(self.buffer, self.key)
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::hash::{BuildHasherDefault};
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer);
        assert_ne!(0, hasher_a.key);
        assert_ne!(hasher_a.buffer, hasher_a.key);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer, hasher_b.buffer);
        assert_eq!(hasher_a.key, hasher_b.key);
    }

    #[test]
    fn test_hash() {
        let value: u64 = 1 << 32;
        let result = hash(value, 0);
        let value2: u64 = 1;
        let result2= hash(value2, 0);
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}<commit_msg>Stringthen callback algorithm<commit_after>use crate::convert::{Convert};
use std::hash::{Hasher};
use const_random::const_random;

///These constants come from splitmix64 which is derived from Java's SplitableRandom, which is based on DotMix and MurmurHash3.
const MULTIPLES: [u64; 2] = [0xBF58476D1CE4E5B9, 0x94D049BB133111EB];
const INCREMENT: u64 = 0x9e3779b97f4a7c15;

const DEFAULT_KEYS: [u64; 2] = [const_random!(u64), const_random!(u64)];

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [AHasher] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    key: u64,
}

/// Provides a [Hasher] is typically used (e.g. by [HashMap]) to create
/// [AHasher]s for each key such that they are hashed independently of one
/// another, since [AHasher]s contain state.
///
/// Constructs a new [AHasher] with compile time generated constants keys.
/// So the key will be the same from one instance to another,
/// but different from build to the next. So if it is possible for a potential
/// attacker to have access to your compiled binary it would be better
/// to specify keys generated at runtime.
///
/// # Examples
///
/// ```
/// use ahash::AHasher;
/// use std::hash::Hasher;
///
/// let mut hasher_1 = AHasher::default();
/// let mut hasher_2 = AHasher::default();
///
/// hasher_1.write_u32(8128);
/// hasher_2.write_u32(8128);
///
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
/// ```
/// [Hasher]: std::hash::Hasher
/// [HashMap]: std::collections::HashMap
impl Default for AHasher {
    #[inline]
    fn default() -> AHasher {
        AHasher {buffer: DEFAULT_KEYS[0], key: DEFAULT_KEYS[1]}
    }
}
impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> AHasher {
        AHasher { buffer: key0, key: key1 }
    }

    #[inline(always)]
    fn update(&mut self, new_data: u64) {
        let value = new_data ^ self.key;
        self.buffer ^= ((value >> 30) ^ value).wrapping_mul(MULTIPLES[0]);
        self.key = self.key.wrapping_add(INCREMENT);
    }
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        let data: [u64;2] = i.convert();
        self.update(data[0]);
        self.update(data[1]);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        self.key ^= length;
        while data.len() >= 8 {
            let (block, rest) = data.split_at(8);
            let val: u64 = as_array!(block, 8).convert();
            self.update(val);
            data = rest;
        }
        if data.len() >= 4 {
            let (block, rest) = data.split_at(4);
            let val: u32 = as_array!(block, 4).convert();
            self.update(val as u64);
            data = rest;
        }
        if data.len() >= 2 {
            let (block, rest) = data.split_at(2);
            let val: u16 = as_array!(block, 2).convert();
            self.update(val as u64);
            data = rest;
        }
        if data.len() >= 1 {
            self.update(data[0] as u64);
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result = self.buffer ^ self.key;
        let result = (result ^ (result >> 27)).wrapping_mul(MULTIPLES[1]);
        result ^ (result >> 31)
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::hash::{BuildHasherDefault};
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer);
        assert_ne!(0, hasher_a.key);
        assert_ne!(hasher_a.buffer, hasher_a.key);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer, hasher_b.buffer);
        assert_eq!(hasher_a.key, hasher_b.key);
    }

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0,0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0,0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
fn main(){
	let mut f = File::open("input.txt").unwrap();
	let mut s = String::new();
	f.read_to_string(&mut s);
	let mut output = 0;
  for ch in s.chars(){
    match ch{
      '(' => output += 1,
      ')' => output -= 1,
      _ => output += 0
      }
  }
  println!("{}",output);
}
<commit_msg>Update problem1.rs<commit_after>use std::fs::File;
use std::io::prelude::*;
fn main(){
	let mut f = File::open("input.txt").unwrap();
	let mut s = String::new();
	f.read_to_string(&mut s);
	let mut output = 0;
	for ch in s.chars(){
	match ch{
		'(' => output += 1,
		')' => output -= 1,
		_ => output += 0
		}
}
  println!("{}",output);
}
<|endoftext|>


<commit_before>use std;
use rustc;

import std::fs;
import std::getopts;
import std::getopts::optopt;
import std::getopts::opt_present;
import std::getopts::opt_str;
import std::io;
import std::io::stdout;
import std::vec;
import std::str;
import std::uint;
import std::option;

import rustc::syntax::ast;
import rustc::syntax::fold;
import rustc::syntax::visit;
import rustc::syntax::codemap;
import rustc::syntax::parse::parser;
import rustc::syntax::print::pprust;

fn write_file(filename: &str, content: &str) {
    io::file_writer(filename, [io::create, io::truncate]).write_str(content);
    // Work around https://github.com/graydon/rust/issues/726
    std::run::run_program("chmod", ["644", filename]);
}

fn file_contains(filename: &str, needle: &str) -> bool {
    let contents = io::read_whole_file_str(filename);
    ret str::find(contents, needle) != -1;
}

fn contains(haystack: &str, needle: &str) -> bool {
    str::find(haystack, needle) != -1
}

fn find_rust_files(files: &mutable [str], path: &str) {
    if str::ends_with(path, ".rs") {
        if file_contains(path, "xfail-test") {
            //log_err "Skipping " + path + " because it is marked as xfail-test";
        } else { files += [path]; }
    } else if fs::file_is_dir(path)
        && str::find(path, "compile-fail") == -1 {
        for p in fs::list_dir(path) {
            find_rust_files(files, p);
        }
    }
}

fn safe_to_steal(e: ast::expr_) -> bool {
    alt e {

      // pretty-printer precedence issues -- https://github.com/graydon/rust/issues/670
      ast::expr_unary(_, _) {
        false
      }
      ast::expr_lit(lit) {
        alt lit.node {
          ast::lit_str(_) { true }
          ast::lit_char(_) { true }
          ast::lit_int(_) { false }
          ast::lit_uint(_) { false }
          ast::lit_mach_int(_, _) { false }
          ast::lit_float(_) { false }
          ast::lit_mach_float(_, _) { false }
          ast::lit_nil. { true }
          ast::lit_bool(_) { true }
        }
      }
      ast::expr_cast(_, _) { false }
      ast::expr_assert(_) { false }
      ast::expr_binary(_, _, _) { false }
      ast::expr_assign(_, _) { false }
      ast::expr_assign_op(_, _, _) { false }
      ast::expr_fail(option::none.) {
        false
        /* https://github.com/graydon/rust/issues/764 */

      }
      ast::expr_ret(option::none.) { false }
      ast::expr_put(option::none.) { false }

      ast::expr_ret(_) {
        false
        /* lots of code generation issues, such as https://github.com/graydon/rust/issues/770 */

      }
      ast::expr_fail(_) { false }

      _ {
        true
      }
    }
}

fn steal_exprs(crate: &ast::crate) -> [ast::expr] {
    let exprs: @mutable [ast::expr] = @mutable [];
    // "Stash" is not type-parameterized because of the need for safe_to_steal
    fn stash_expr(es: @mutable [ast::expr], e: &@ast::expr) {
        if safe_to_steal(e.node) {
            *es += [*e];
        } else {/* now my indices are wrong :( */ }
    }
    let v =
        visit::mk_simple_visitor(@{visit_expr: bind stash_expr(exprs, _)
                                      with *visit::default_simple_visitor()});
    visit::visit_crate(crate, (), v);;
    *exprs
}

// https://github.com/graydon/rust/issues/652
fn safe_to_replace(e: ast::expr_) -> bool {
    alt e {
      ast::expr_if(_, _, _) { false }
      ast::expr_block(_) { false }
      _ { true }
    }
}

// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
fn replace_expr_in_crate(crate: &ast::crate, i: uint, newexpr: ast::expr_) ->
   ast::crate {
    let j: @mutable uint = @mutable 0u;
    fn fold_expr_rep(j_: @mutable uint, i_: uint, newexpr_: &ast::expr_,
                     original: &ast::expr_, fld: fold::ast_fold) ->
       ast::expr_ {
        *j_ += 1u;
        if i_ + 1u == *j_ && safe_to_replace(original) {
            newexpr_
        } else { fold::noop_fold_expr(original, fld) }
    }
    let afp =
        {fold_expr: bind fold_expr_rep(j, i, newexpr, _, _)
            with *fold::default_ast_fold()};
    let af = fold::make_fold(afp);
    let crate2: @ast::crate = @af.fold_crate(crate);
    fold::dummy_out(af); // work around a leak (https://github.com/graydon/rust/issues/651)
    ;
    *crate2
}

iter under(n: uint) -> uint {
    let i: uint = 0u;
    while i < n { put i; i += 1u; }
}

fn devnull() -> io::writer { std::io::string_writer().get_writer() }

fn as_str(f: fn(io::writer)) -> str {
    let w = std::io::string_writer();
    f(w.get_writer());
    ret w.get_str();
}

fn check_variants_of_ast(crate: &ast::crate, codemap: &codemap::codemap,
                         filename: &str) {
    let exprs = steal_exprs(crate);
    let exprsL = vec::len(exprs);
    if exprsL < 100u {
        for each i: uint in under(uint::min(exprsL, 20u)) {
            log_err "Replacing... " + pprust::expr_to_str(@exprs[i]);
            for each j: uint in under(uint::min(exprsL, 5u)) {
                log_err "With... " + pprust::expr_to_str(@exprs[j]);
                let crate2 = @replace_expr_in_crate(crate, i, exprs[j].node);
                // It would be best to test the *crate* for stability, but testing the
                // string for stability is easier and ok for now.
                let str3 =
                    as_str(bind pprust::print_crate(codemap, crate2,
                                                    filename,
                                                    io::string_reader(""), _,
                                                    pprust::no_ann()));
                // 1u would be sane here, but the pretty-printer currently has lots of whitespace and paren issues,
                // and https://github.com/graydon/rust/issues/766 is hilarious.
                check_roundtrip_convergence(str3, 7u);
                //check_whole_compiler(str3);
            }
        }
    }
}

// We'd find more bugs if we could take an AST here, but
// - that would find many "false positives" or unimportant bugs
// - that would be tricky, requiring use of tasks or serialization or randomness.
// This seems to find plenty of bugs as it is :)
fn check_whole_compiler(code: &str) {
    let filename = "test.rs";
    write_file(filename, code);
    let p =
        std::run::program_output(
            "/Users/jruderman/code/rust/build/stage1/rustc",
            ["-c", filename]);

    //log_err #fmt("Status: %d", p.status);
    //log_err "Output: " + p.out;
    if p.err != "" {
        if false {
        } else {
            log_err "Stderr: " + p.err;
            fail "Unfamiliar error message";
        }
    } else if p.status == 256 {
        if !contains(p.out, "error:") {
            fail "Exited with status 256 without a span-error";
        }
    } else if p.status == 11 {
        log_err "What is this I don't even";
    } else if p.status != 0 { fail "Unfamiliar status code"; }
}

fn parse_and_print(code: &str) -> str {
    let filename = "tmp.rs";
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    //write_file(filename, code);
    let crate = parser::parse_crate_from_source_str(
        filename, code, [], sess);
    ret as_str(bind pprust::print_crate(sess.cm, crate,
                                        filename,
                                        io::string_reader(code), _,
                                        pprust::no_ann()));
}

fn content_is_dangerous_to_modify(code: &str) -> bool {
    let dangerous_patterns =
        ["obj", // not safe to steal; https://github.com/graydon/rust/issues/761
         "#macro", // not safe to steal things inside of it, because they have a special syntax
         "#", // strange representation of the arguments to #fmt, for example
         " be ", // don't want to replace its child with a non-call: "Non-call expression in tail call"
         "@"]; // hangs when compiling: https://github.com/graydon/rust/issues/768

    for p: str in dangerous_patterns { if contains(code, p) { ret true; } }
    ret false;
}

fn content_is_confusing(code: &str) ->
   bool { // https://github.com/graydon/rust/issues/671
          // https://github.com/graydon/rust/issues/669
          // https://github.com/graydon/rust/issues/669
          // https://github.com/graydon/rust/issues/669
          // crazy rules enforced by parser rather than typechecker?
          // more precedence issues
          // more precedence issues?

    let confusing_patterns =
        ["#macro", "][]", "][mutable]", "][mutable ]", "self", "spawn",
         "bind", "\n\n\n\n\n", // https://github.com/graydon/rust/issues/759
         " : ", // https://github.com/graydon/rust/issues/760
         "if ret", "alt ret", "if fail", "alt fail"];

    for p: str in confusing_patterns { if contains(code, p) { ret true; } }
    ret false;
}

fn file_is_confusing(filename: &str) -> bool {

    // https://github.com/graydon/rust/issues/674

    // something to do with () as a lone pattern

    // an issue where -2147483648 gains an
    // extra negative sign each time through,
    // which i can't reproduce using "rustc
    // --pretty normal"???
    let confusing_files =
        ["block-expr-precedence.rs", "nil-pattern.rs",
         "syntax-extension-fmt.rs",
         "newtype.rs"]; // modifying it hits something like https://github.com/graydon/rust/issues/670

    for f in confusing_files { if contains(filename, f) { ret true; } }

    ret false;
}

fn check_roundtrip_convergence(code: &str, maxIters: uint) {

    let i = 0u;
    let new = code;
    let old = code;

    while i < maxIters {
        old = new;
        if content_is_confusing(old) { ret; }
        new = parse_and_print(old);
        if old == new { break; }
        i += 1u;
    }

    if old == new {
        log_err #fmt["Converged after %u iterations", i];
    } else {
        log_err #fmt["Did not converge after %u iterations!", i];
        write_file("round-trip-a.rs", old);
        write_file("round-trip-b.rs", new);
        std::run::run_program("diff",
                              ["-w", "-u", "round-trip-a.rs",
                               "round-trip-b.rs"]);
        fail "Mismatch";
    }
}

fn check_convergence(files: &[str]) {
    log_err #fmt["pp convergence tests: %u files", vec::len(files)];
    for file in files {
        if !file_is_confusing(file) {
            let s = io::read_whole_file_str(file);
            if !content_is_confusing(s) {
                log_err #fmt["pp converge: %s", file];
                // Change from 7u to 2u when https://github.com/graydon/rust/issues/759 is fixed
                check_roundtrip_convergence(s, 7u);
            }
        }
    }
}

fn check_variants(files: &[str]) {
    for file in files {
        if !file_is_confusing(file) {
            let s = io::read_whole_file_str(file);
            if content_is_dangerous_to_modify(s) || content_is_confusing(s) {
                cont;
            }
            log_err "check_variants: " + file;
            let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
            let crate =
                parser::parse_crate_from_source_str(
                    file,
                    s, [], sess);
            log_err as_str(bind pprust::print_crate(sess.cm, crate,
                                                    file,
                                                    io::string_reader(s), _,
                                                    pprust::no_ann()));
            check_variants_of_ast(*crate, sess.cm, file);
        }
    }
}

fn main(args: [str]) {
    if vec::len(args) != 2u {
        log_err #fmt["usage: %s <testdir>", args[0]];
        ret;
    }
    let files = [];
    let root = args[1];

    find_rust_files(files, root);
    check_convergence(files);
    check_variants(files);
    log_err "Fuzzer done";
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Fuzzer: update lists of known bugs<commit_after>use std;
use rustc;

import std::fs;
import std::getopts;
import std::getopts::optopt;
import std::getopts::opt_present;
import std::getopts::opt_str;
import std::io;
import std::io::stdout;
import std::vec;
import std::str;
import std::uint;
import std::option;

import rustc::syntax::ast;
import rustc::syntax::fold;
import rustc::syntax::visit;
import rustc::syntax::codemap;
import rustc::syntax::parse::parser;
import rustc::syntax::print::pprust;

fn write_file(filename: &str, content: &str) {
    io::file_writer(filename, [io::create, io::truncate]).write_str(content);
    // Work around https://github.com/graydon/rust/issues/726
    std::run::run_program("chmod", ["644", filename]);
}

fn file_contains(filename: &str, needle: &str) -> bool {
    let contents = io::read_whole_file_str(filename);
    ret str::find(contents, needle) != -1;
}

fn contains(haystack: &str, needle: &str) -> bool {
    str::find(haystack, needle) != -1
}

fn find_rust_files(files: &mutable [str], path: &str) {
    if str::ends_with(path, ".rs") {
        if file_contains(path, "xfail-test") {
            //log_err "Skipping " + path + " because it is marked as xfail-test";
        } else { files += [path]; }
    } else if fs::file_is_dir(path)
        && str::find(path, "compile-fail") == -1 {
        for p in fs::list_dir(path) {
            find_rust_files(files, p);
        }
    }
}

fn safe_to_steal(e: ast::expr_) -> bool {
    alt e {

      // https://github.com/graydon/rust/issues/890
      ast::expr_lit(lit) {
        alt lit.node {
          ast::lit_str(_) { true }
          ast::lit_char(_) { true }
          ast::lit_int(_) { false }
          ast::lit_uint(_) { true }
          ast::lit_mach_int(_, _) { false }
          ast::lit_float(_) { false }
          ast::lit_mach_float(_, _) { false }
          ast::lit_nil. { true }
          ast::lit_bool(_) { true }
        }
      }

      // https://github.com/graydon/rust/issues/890
      ast::expr_cast(_, _) { false }
      ast::expr_assert(_) { false }
      ast::expr_binary(_, _, _) { false }
      ast::expr_assign(_, _) { false }
      ast::expr_assign_op(_, _, _) { false }

      // https://github.com/graydon/rust/issues/764
      ast::expr_fail(option::none.) { false }
      ast::expr_ret(option::none.) { false }
      ast::expr_put(option::none.) { false }

      // These prefix-operator keywords are not being parenthesized when in callee positions.
      // https://github.com/graydon/rust/issues/891
      ast::expr_ret(_) { false }
      ast::expr_put(_) { false }
      ast::expr_check(_, _) { false }
      ast::expr_log(_, _) { false }

      _ { true }
    }
}

fn steal_exprs(crate: &ast::crate) -> [ast::expr] {
    let exprs: @mutable [ast::expr] = @mutable [];
    // "Stash" is not type-parameterized because of the need for safe_to_steal
    fn stash_expr(es: @mutable [ast::expr], e: &@ast::expr) {
        if safe_to_steal(e.node) {
            *es += [*e];
        } else {/* now my indices are wrong :( */ }
    }
    let v =
        visit::mk_simple_visitor(@{visit_expr: bind stash_expr(exprs, _)
                                      with *visit::default_simple_visitor()});
    visit::visit_crate(crate, (), v);;
    *exprs
}

// https://github.com/graydon/rust/issues/652
fn safe_to_replace(e: ast::expr_) -> bool {
    alt e {
      ast::expr_if(_, _, _) { false }
      ast::expr_block(_) { false }
      _ { true }
    }
}

// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
fn replace_expr_in_crate(crate: &ast::crate, i: uint, newexpr: ast::expr_) ->
   ast::crate {
    let j: @mutable uint = @mutable 0u;
    fn fold_expr_rep(j_: @mutable uint, i_: uint, newexpr_: &ast::expr_,
                     original: &ast::expr_, fld: fold::ast_fold) ->
       ast::expr_ {
        *j_ += 1u;
        if i_ + 1u == *j_ && safe_to_replace(original) {
            newexpr_
        } else { fold::noop_fold_expr(original, fld) }
    }
    let afp =
        {fold_expr: bind fold_expr_rep(j, i, newexpr, _, _)
            with *fold::default_ast_fold()};
    let af = fold::make_fold(afp);
    let crate2: @ast::crate = @af.fold_crate(crate);
    fold::dummy_out(af); // work around a leak (https://github.com/graydon/rust/issues/651)
    ;
    *crate2
}

iter under(n: uint) -> uint {
    let i: uint = 0u;
    while i < n { put i; i += 1u; }
}

fn devnull() -> io::writer { std::io::string_writer().get_writer() }

fn as_str(f: fn(io::writer)) -> str {
    let w = std::io::string_writer();
    f(w.get_writer());
    ret w.get_str();
}

fn check_variants_of_ast(crate: &ast::crate, codemap: &codemap::codemap,
                         filename: &str) {
    let exprs = steal_exprs(crate);
    let exprsL = vec::len(exprs);
    if exprsL < 100u {
        for each i: uint in under(uint::min(exprsL, 20u)) {
            log_err "Replacing... " + pprust::expr_to_str(@exprs[i]);
            for each j: uint in under(uint::min(exprsL, 5u)) {
                log_err "With... " + pprust::expr_to_str(@exprs[j]);
                let crate2 = @replace_expr_in_crate(crate, i, exprs[j].node);
                // It would be best to test the *crate* for stability, but testing the
                // string for stability is easier and ok for now.
                let str3 =
                    as_str(bind pprust::print_crate(codemap, crate2,
                                                    filename,
                                                    io::string_reader(""), _,
                                                    pprust::no_ann()));
                check_roundtrip_convergence(str3, 1u);
                //check_whole_compiler(str3);
            }
        }
    }
}

// We'd find more bugs if we could take an AST here, but
// - that would find many "false positives" or unimportant bugs
// - that would be tricky, requiring use of tasks or serialization or randomness.
// This seems to find plenty of bugs as it is :)
fn check_whole_compiler(code: &str) {
    let filename = "test.rs";
    write_file(filename, code);
    let p =
        std::run::program_output(
            "/Users/jruderman/code/rust/build/stage1/rustc",
            ["-c", filename]);

    //log_err #fmt("Status: %d", p.status);
    //log_err "Output: " + p.out;
    if p.err != "" {
        if false {
        } else {
            log_err "Stderr: " + p.err;
            fail "Unfamiliar error message";
        }
    } else if p.status == 256 {
        if !contains(p.out, "error:") {
            fail "Exited with status 256 without a span-error";
        }
    } else if p.status == 11 {
        log_err "What is this I don't even";
    } else if p.status != 0 { fail "Unfamiliar status code"; }
}

fn parse_and_print(code: &str) -> str {
    let filename = "tmp.rs";
    let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
    //write_file(filename, code);
    let crate = parser::parse_crate_from_source_str(
        filename, code, [], sess);
    ret as_str(bind pprust::print_crate(sess.cm, crate,
                                        filename,
                                        io::string_reader(code), _,
                                        pprust::no_ann()));
}

fn content_is_dangerous_to_modify(code: &str) -> bool {
    let dangerous_patterns =
        ["#macro", // not safe to steal things inside of it, because they have a special syntax
         "#",      // strange representation of the arguments to #fmt, for example
         " be "];  // don't want to replace its child with a non-call: "Non-call expression in tail call"

    for p: str in dangerous_patterns { if contains(code, p) { ret true; } }
    ret false;
}

fn content_is_confusing(code: &str) -> bool {
    let confusing_patterns =
        ["self",       // crazy rules enforced by parser rather than typechecker?
        "spawn",       // precedence issues?
         "bind",       // precedence issues?
         "\n\n\n\n\n"  // https://github.com/graydon/rust/issues/850
        ];

    for p: str in confusing_patterns { if contains(code, p) { ret true; } }
    ret false;
}

fn file_is_confusing(filename: &str) -> bool {
    let confusing_files = [];

    for f in confusing_files { if contains(filename, f) { ret true; } }

    ret false;
}

fn check_roundtrip_convergence(code: &str, maxIters: uint) {

    let i = 0u;
    let new = code;
    let old = code;

    while i < maxIters {
        old = new;
        if content_is_confusing(old) { ret; }
        new = parse_and_print(old);
        if old == new { break; }
        i += 1u;
    }

    if old == new {
        log_err #fmt["Converged after %u iterations", i];
    } else {
        log_err #fmt["Did not converge after %u iterations!", i];
        write_file("round-trip-a.rs", old);
        write_file("round-trip-b.rs", new);
        std::run::run_program("diff",
                              ["-w", "-u", "round-trip-a.rs",
                               "round-trip-b.rs"]);
        fail "Mismatch";
    }
}

fn check_convergence(files: &[str]) {
    log_err #fmt["pp convergence tests: %u files", vec::len(files)];
    for file in files {
        if !file_is_confusing(file) {
            let s = io::read_whole_file_str(file);
            if !content_is_confusing(s) {
                log_err #fmt["pp converge: %s", file];
                // Change from 7u to 2u once https://github.com/graydon/rust/issues/850 is fixed
                check_roundtrip_convergence(s, 7u);
            }
        }
    }
}

fn check_variants(files: &[str]) {
    for file in files {
        if !file_is_confusing(file) {
            let s = io::read_whole_file_str(file);
            if content_is_dangerous_to_modify(s) || content_is_confusing(s) {
                cont;
            }
            log_err "check_variants: " + file;
            let sess = @{cm: codemap::new_codemap(), mutable next_id: 0};
            let crate =
                parser::parse_crate_from_source_str(
                    file,
                    s, [], sess);
            log_err as_str(bind pprust::print_crate(sess.cm, crate,
                                                    file,
                                                    io::string_reader(s), _,
                                                    pprust::no_ann()));
            check_variants_of_ast(*crate, sess.cm, file);
        }
    }
}

fn main(args: [str]) {
    if vec::len(args) != 2u {
        log_err #fmt["usage: %s <testdir>", args[0]];
        ret;
    }
    let files = [];
    let root = args[1];

    find_rust_files(files, root);
    check_convergence(files);
    check_variants(files);
    log_err "Fuzzer done";
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>