#![feature(naked_functions)]
#![deny(unconditional_recursion)]

// #[derive(Debug)]
// struct Stat {
//     sum: isize,
//     count: isize,
//     avg: isize,
//     min: isize,
//     max: isize,
// }
//
// macro_rules! sum {
//     () => (0);
//     ($e:expr) => ( $e );
//     ($head:expr, $($tail:expr),*) => { $head + sum!($($tail),*)};
// }
//
// macro_rules! count {
//     () => (0);
//     ($e:expr) => ( 1 );
//     ($head:expr, $($tail:expr),*) => { 1 + count!($($tail),*) };
// }
//
// #[inline(never)]
// fn push(a: isize, b: isize, c: isize) -> isize {
//     sum!(a, b, c)
// }
//
// macro_rules! avg{
//     ($($all:expr),+) => {
//         sum!($($all),+) / count!($($all),+)
//     };
// }
//
// macro_rules! max {
//     ($x:expr) => ( $x );
//     ($x:expr, $($xs:expr),+) => {
//         {
//             use std::cmp::max;
//             max($x, max!( $($xs),+ ))
//         }
//     };
// }
//
// macro_rules! min {
//     ($x:expr) => ( $x );
//     ($x:expr, $($xs:expr),+) => {
//         {
//             use std::cmp::min;
//             min($x, min!( $($xs),+ ))
//         }
//     };
// }
// #[inline(never)]
// fn stats(a: isize, b: isize, c: isize) -> Stat {
//     let sum = sum(a, b, c);
//     let count = count!(a, b, c);
//     let avg = avg!(a, b, c);
//     let min = min!(a, b, c);
//     let max = max!(a, b, c);
//     Stat {
//         sum,
//         count,
//         avg,
//         min,
//         max,
//     }
// }
//
// #[inline(never)]
// fn sum(a: isize, b: isize, c: isize) -> isize {
// sum!(a, b, c)
// }
#[inline(never)]
fn passthrough(a: isize) -> isize {
    let b = a;
    b
}

#[inline(never)]
fn caller() {
    let a = passthrough(1);
    let b = a * 2;
    printer(&a, &b);
}

#[inline(never)]
fn printer(a: &isize, b: &isize) {
    println!("2*{}={}", a, b)
}

#[inline(never)]
fn modifier() {
    let v: usize = 0;
    let v_addr = (&v as *const usize) as usize;
    unsafe {
        *((v_addr + 1 * 8) as *mut usize) = simple_printer as usize;
    }
}

#[naked]
fn simple_printer() {
    eprint!("I wonder who called me?");
}

#[inline(never)]
fn huge_stack() {
    const SLICE_LENGTH: usize = 0x100000000;
    let slice: [u64; SLICE_LENGTH] = [0xdeadbeef; SLICE_LENGTH];
    let slice_start_addr = &slice[0] as *const u64;
    let slice_end_addr = &slice[SLICE_LENGTH - 1] as *const u64;
    println!("{:?} - {:?} = {:?}",
             slice_start_addr,
             slice_end_addr,
             (slice_end_addr as usize - slice_start_addr as usize) / std::mem::size_of::<usize>());
}

// fn recurse(n: u64) {
    // recurse(n + 1);
// }

fn a() { a(); }
fn main() { a(); }



// fn main() {
    // // modifier();
    // huge_stack();
    // println!("main exiting")
// }