<commit_before>#![allow(non_camel_case_types, non_snake_case)]
pub mod constants;
use self::constants::*;

use ncurses::{box_, getmouse, keyname, setlocale, LcCategory, COLORS, COLOR_PAIRS};
use ncurses::ll::{chtype, ungetch, wattroff, wattron, wattrset, MEVENT, NCURSES_ATTR_T, WINDOW};
use ncurses::ll::{resize_term, wgetch, wmouse_trafo};

use libc::c_int;
use input::Input;

use std::string::FromUtf8Error;

pub fn pre_init() {
    setlocale(LcCategory::all, "");
}

pub fn _attron(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes as NCURSES_ATTR_T) }
}

pub fn _attroff(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes as NCURSES_ATTR_T) }
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as NCURSES_ATTR_T) }
}

pub fn _COLORS() -> i32 {
    COLORS()
}

pub fn _COLOR_PAIRS() -> i32 {
    COLOR_PAIRS()
}

pub fn _draw_box(w: WINDOW, verch: chtype, horch: chtype) -> i32 {
    box_(w, verch, horch)
}

pub fn _getmouse() -> Result<MEVENT, i32> {
    let mut mevent = MEVENT {
        id: 0,
        x: 0,
        y: 0,
        z: 0,
        bstate: 0,
    };
    let error = getmouse(&mut mevent);
    if error == 0 {
        Ok(mevent)
    } else {
        Err(error)
    }
}

pub fn _keyname(code: i32) -> Option<String> {
    keyname(code)
}

pub fn _resize_term(nlines: i32, ncols: i32) -> i32 {
    unsafe { resize_term(nlines, ncols) }
}

pub fn _set_blink(_: bool) -> i32 {
    0 // Not supported
}

pub fn _set_title(_: &str) {
    //Not supported
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Option<Input> {
    let index = if i <= KEY_F15 {
        i - KEY_OFFSET
    } else {
        i - KEY_OFFSET - 48
    };
    if index < 0 || index as usize >= SPECIAL_KEY_CODES.len() {
        None
    } else {
        Some(SPECIAL_KEY_CODES[index as usize])
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    match *input {
        Input::Character(c) => {
            // Need to convert to UTF-8 bytes, it's how we get them from getch()
            let mut utf8_buffer = [0; 4];
            c.encode_utf8(&mut utf8_buffer)
                .as_bytes()
                .into_iter()
                .rev()
                .map(|x| unsafe { ungetch(*x as c_int) })
                .fold(0, |res, x| i32::min(res, x))
        }
        Input::Unknown(i) => unsafe { ungetch(i) },
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return unsafe { ungetch(result) };
                    } else {
                        return unsafe { ungetch(result + 48) };
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

pub fn _wgetch(w: WINDOW) -> Option<Input> {
    let i = unsafe { wgetch(w) };
    if i < 0 {
        None
    } else {
        Some(to_special_keycode(i).unwrap_or_else(|| {
            // Assume that on Linux input is UTF-8
            fn try_decode(mut v: Vec<u8>, w: WINDOW) -> Result<String, FromUtf8Error> {
                let res = String::from_utf8(v.clone());
                if res.is_err() && v.len() < 4 {
                    let next_byte = unsafe { wgetch(w) };
                    v.push(next_byte as u8);
                    try_decode(v, w)
                } else {
                    res
                }
            }

            let v = vec![i as u8];
            try_decode(v, w)
                .map(|s| Input::Character(s.chars().next().unwrap()))
                .unwrap_or_else(|error| {
                    warn!("Decoding input as UTF-8 failed: {:?}", error);
                    Input::Unknown(i)
                })
        }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use input::Input;
    use ncurses::{endwin, initscr};

    #[test]
    fn test_key_dl_to_special_keycode() {
        let keyDl = 0o510;
        assert_eq!(Input::KeyDL, to_special_keycode(keyDl).unwrap());
    }

    #[test]
    fn test_key_f15_to_input() {
        let keyF15 = 0o410 + 15;
        assert_eq!(Input::KeyF15, to_special_keycode(keyF15).unwrap());
    }

    #[test]
    fn test_key_up_to_input() {
        let keyUp = 0o403;
        assert_eq!(Input::KeyUp, to_special_keycode(keyUp).unwrap());
    }

    #[test]
    fn test_ungetch() {
        let w = initscr();

        let chars = [
            'a', 'b', 'c', 'ä', 'ö', 'å', 'A', 'B', 'C', 'Ä', 'Ö', 'Å', '𤭢', '𐍈',
            '€', 'ᚠ', 'ᛇ', 'ᚻ', 'þ', 'ð', 'γ', 'λ', 'ώ', 'б', 'е', 'р', 'ვ',
            'ე', 'პ', 'ხ', 'இ', 'ங', 'க', 'ಬ', 'ಇ', 'ಲ', 'ಸ',
        ];

        chars.into_iter().for_each(|c| {
            _ungetch(&Input::Character(*c));
            assert_eq!(_wgetch(w).unwrap(), Input::Character(*c));
        });

        SPECIAL_KEY_CODES.into_iter().for_each(|i| {
            _ungetch(i);
            assert_eq!(_wgetch(w).unwrap(), *i);
        });

        endwin();
    }

}
<commit_msg>Remove unused import<commit_after>#![allow(non_camel_case_types, non_snake_case)]
pub mod constants;
use self::constants::*;

use ncurses::{box_, getmouse, keyname, setlocale, LcCategory, COLORS, COLOR_PAIRS};
use ncurses::ll::{chtype, ungetch, wattroff, wattron, wattrset, MEVENT, NCURSES_ATTR_T, WINDOW};
use ncurses::ll::{resize_term, wgetch};

use libc::c_int;
use input::Input;

use std::string::FromUtf8Error;

pub fn pre_init() {
    setlocale(LcCategory::all, "");
}

pub fn _attron(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes as NCURSES_ATTR_T) }
}

pub fn _attroff(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes as NCURSES_ATTR_T) }
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as NCURSES_ATTR_T) }
}

pub fn _COLORS() -> i32 {
    COLORS()
}

pub fn _COLOR_PAIRS() -> i32 {
    COLOR_PAIRS()
}

pub fn _draw_box(w: WINDOW, verch: chtype, horch: chtype) -> i32 {
    box_(w, verch, horch)
}

pub fn _getmouse() -> Result<MEVENT, i32> {
    let mut mevent = MEVENT {
        id: 0,
        x: 0,
        y: 0,
        z: 0,
        bstate: 0,
    };
    let error = getmouse(&mut mevent);
    if error == 0 {
        Ok(mevent)
    } else {
        Err(error)
    }
}

pub fn _keyname(code: i32) -> Option<String> {
    keyname(code)
}

pub fn _resize_term(nlines: i32, ncols: i32) -> i32 {
    unsafe { resize_term(nlines, ncols) }
}

pub fn _set_blink(_: bool) -> i32 {
    0 // Not supported
}

pub fn _set_title(_: &str) {
    //Not supported
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Option<Input> {
    let index = if i <= KEY_F15 {
        i - KEY_OFFSET
    } else {
        i - KEY_OFFSET - 48
    };
    if index < 0 || index as usize >= SPECIAL_KEY_CODES.len() {
        None
    } else {
        Some(SPECIAL_KEY_CODES[index as usize])
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    match *input {
        Input::Character(c) => {
            // Need to convert to UTF-8 bytes, it's how we get them from getch()
            let mut utf8_buffer = [0; 4];
            c.encode_utf8(&mut utf8_buffer)
                .as_bytes()
                .into_iter()
                .rev()
                .map(|x| unsafe { ungetch(*x as c_int) })
                .fold(0, |res, x| i32::min(res, x))
        }
        Input::Unknown(i) => unsafe { ungetch(i) },
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return unsafe { ungetch(result) };
                    } else {
                        return unsafe { ungetch(result + 48) };
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

pub fn _wgetch(w: WINDOW) -> Option<Input> {
    let i = unsafe { wgetch(w) };
    if i < 0 {
        None
    } else {
        Some(to_special_keycode(i).unwrap_or_else(|| {
            // Assume that on Linux input is UTF-8
            fn try_decode(mut v: Vec<u8>, w: WINDOW) -> Result<String, FromUtf8Error> {
                let res = String::from_utf8(v.clone());
                if res.is_err() && v.len() < 4 {
                    let next_byte = unsafe { wgetch(w) };
                    v.push(next_byte as u8);
                    try_decode(v, w)
                } else {
                    res
                }
            }

            let v = vec![i as u8];
            try_decode(v, w)
                .map(|s| Input::Character(s.chars().next().unwrap()))
                .unwrap_or_else(|error| {
                    warn!("Decoding input as UTF-8 failed: {:?}", error);
                    Input::Unknown(i)
                })
        }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use input::Input;
    use ncurses::{endwin, initscr};

    #[test]
    fn test_key_dl_to_special_keycode() {
        let keyDl = 0o510;
        assert_eq!(Input::KeyDL, to_special_keycode(keyDl).unwrap());
    }

    #[test]
    fn test_key_f15_to_input() {
        let keyF15 = 0o410 + 15;
        assert_eq!(Input::KeyF15, to_special_keycode(keyF15).unwrap());
    }

    #[test]
    fn test_key_up_to_input() {
        let keyUp = 0o403;
        assert_eq!(Input::KeyUp, to_special_keycode(keyUp).unwrap());
    }

    #[test]
    fn test_ungetch() {
        let w = initscr();

        let chars = [
            'a', 'b', 'c', 'ä', 'ö', 'å', 'A', 'B', 'C', 'Ä', 'Ö', 'Å', '𤭢', '𐍈',
            '€', 'ᚠ', 'ᛇ', 'ᚻ', 'þ', 'ð', 'γ', 'λ', 'ώ', 'б', 'е', 'р', 'ვ',
            'ე', 'პ', 'ხ', 'இ', 'ங', 'க', 'ಬ', 'ಇ', 'ಲ', 'ಸ',
        ];

        chars.into_iter().for_each(|c| {
            _ungetch(&Input::Character(*c));
            assert_eq!(_wgetch(w).unwrap(), Input::Character(*c));
        });

        SPECIAL_KEY_CODES.into_iter().for_each(|i| {
            _ungetch(i);
            assert_eq!(_wgetch(w).unwrap(), *i);
        });

        endwin();
    }

}
<|endoftext|>


<commit_before><commit_msg>prime-factors: Add solution template (#440)<commit_after>pub fn factors(n: u32) -> Vec<u32> {
    unimplemented!("This should calculate the prime factors of {}", n)
}
<|endoftext|>


<commit_before>//! [Church-encoded numerals](https://en.wikipedia.org/wiki/Church_encoding#Church_numerals)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded zero.
///
/// ZERO := λfx.x = λ λ 1
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::zero;
///
/// assert_eq!(format!("{}", zero()), "λλ1");
/// ```
pub fn zero() -> Term { abs(abs(Var(1))) }

/// Applied to a Church-encoded number it produces a Church-encoded boolean, indicating whether its
/// argument is equal to zero.
///
/// IS_ZERO := λn.n (λx.FALSE) TRUE =  λ 1 (λ FALSE) TRUE
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, is_zero};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(is_zero().app(zero())), tru());
/// ```
pub fn is_zero() -> Term { abs(Var(1).app(abs(fls())).app(tru())) }

/// Produces a Church-encoded one.
///
/// ONE := λfx.f x = λ λ 2 1
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::one;
///
/// assert_eq!(format!("{}", one()), "λλ21");
/// ```
pub fn one() -> Term { abs(abs(Var(2).app(Var(1)))) }

/// Applied to a Church-encoded number it produces its successor.
///
/// SUCC := λnfx.f (n f x) = λ λ λ 2 (3 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// ```
pub fn succ() -> Term { abs(abs(abs(Var(2).app(Var(3).app(Var(2)).app(Var(1)))))) }

/// Applied to two Church-encoded numbers it produces their sum.
///
/// PLUS := λmnfx.m f (n f x) = λ λ λ λ 4 2 (3 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, plus};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(plus().app(zero()).app(one())), one());
/// ```
pub fn plus() -> Term { abs(abs(abs(abs(Var(4).app(Var(2)).app(Var(3).app(Var(2)).app(Var(1))))))) }

/// Applied to two Church-encoded numbers it produces their product.
///
/// MULT := λmnf.m (n f) = λ λ λ 3 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, mult};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(mult().app(one()).app(one())), one());
/// ```
pub fn mult() -> Term { abs(abs(abs(Var(3).app(Var(2).app(Var(1)))))) }

/// Applied to two Church-encoded numbers it raises the first one to the power of the second one.
///
/// POW := λbe.e b = λ λ 1 2
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, pow};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(pow().app(one()).app(one())), one());
/// ```
pub fn pow() -> Term { abs(abs(Var(1).app(Var(2)))) }

/// Applied to a Church-encoded number it produces its predecessor.
///
/// PRED := λnfx.n (λgh.h (g f)) (λu.x) (λu.u) = λ λ λ 3 (λ λ 1 (2 4)) (λ 2) (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, pred};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(pred().app(one())), zero());
/// ```
pub fn pred() -> Term { abs(abs(abs(Var(3).app(abs(abs(Var(1).app(Var(2).app(Var(4)))))).app(abs(Var(2))).app(abs(Var(1)))))) }

/// Applied to two Church-encoded numbers it subtracts the second one from the first one.
///
/// SUB := λmn.n PRED m = λ λ 1 PRED 2
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, sub};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(sub().app(one()).app(zero())), one());
/// ```
pub fn sub() -> Term { abs(abs(Var(1).app(pred()).app(Var(2)))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is less than the second one.
///
/// LT := λab.NOT (LEQ b a) = λ λ NOT (LEQ 1 2)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, lt};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(lt().app(zero()).app(one())), tru());
/// ```
pub fn lt() -> Term { abs(abs(not().app(leq().app(Var(1)).app(Var(2))))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is less or egual to the second one.
///
/// LEQ := λmn.IS_ZERO (SUB m n) = λ λ IS_ZERO (SUB 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, leq};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(leq().app(zero()).app(one())), tru());
/// ```
pub fn leq() -> Term { abs(abs(is_zero().app(sub().app(Var(2)).app(Var(1))))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is egual to the second one.
///
/// EQ := λmn.AND (LEQ m n) (LEQ n m) = λ λ AND (LEQ 2 1) (LEQ 1 2)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, eq};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(eq().app(one()).app(one())), tru());
/// ```
pub fn eq() -> Term { abs(abs(and().app(leq().app(Var(2)).app(Var(1))).app(leq().app(Var(1)).app(Var(2))))) }

impl Term {
	/// Returns the value of a Church-encoded number.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::arithmetic::one;
	///
	/// assert_eq!(one().value(), Ok(1));
	/// ```
	pub fn value(&self) -> Result<usize, Error> {
		if let Ok(ref inner) = self.unabs_ref().and_then(|t| t.unabs_ref()) {
			Ok(try!(inner._value()))
		} else {
			Err(NotANum)
		}
	}

	fn _value(&self) -> Result<usize, Error> {
		if let Ok(ref rhs) = self.rhs_ref() {
			Ok(1 + try!(rhs._value()))
		} else if let Var(n) = *self {
			if n == 1 {
				Ok(0)
			} else {
				Err(NotANum)
			}
		} else {
			Err(NotANum)
		}
	}

	/// Checks whether a term is a Church-encoded number.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::arithmetic::one;
	///
	/// assert!(one().is_number());
	/// ```
	pub fn is_number(&self) -> bool { self.value().is_ok() }
}

/// Produces a Church-encoded term with a value of the given natural number.
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, to_cnum};
///
/// assert_eq!(to_cnum(1), one());
/// ```
pub fn to_cnum(n: usize) -> Term {
	let mut inner = Var(1);
	let mut count = n;

	while count > 0 {
		inner = Var(2).app(inner);
		count -= 1;
	}

	abs(abs(inner))
}

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

	#[test]
	fn church_zero() {
		assert_eq!(normalize(is_zero().app(zero())), tru());
		assert_eq!(normalize(is_zero().app(one())), fls());
	}

	#[test]
	fn church_successor() {
		assert_eq!(normalize(succ().app(zero())), one());
		assert_eq!(normalize(succ().app(one())), abs(abs(Var(2).app(Var(2).app(Var(1))))));
		assert_eq!(normalize(succ().app(succ().app(succ().app(zero())))), abs(abs(Var(2).app(Var(2).app(Var(2).app(Var(1)))))));
	}

	#[test]
	fn church_number_identification() {
		for n in 0..5 { assert!(to_cnum(n).is_number()) }
	}

	#[test]
	fn church_number_creation() {
		assert_eq!(to_cnum(0), zero());
		assert_eq!(to_cnum(1), one());
		assert_eq!(to_cnum(2), normalize(succ().app(one())));
	}

	#[test]
	fn church_number_values() {
		for n in 0..10 { assert_eq!(to_cnum(n).value(), Ok(n)) }

		assert_eq!(tru().value(),		Err(NotANum));
		assert_eq!(Var(1).value(),		Err(NotANum));
		assert_eq!(abs(Var(1)).value(),	Err(NotANum));
	}

	#[test]
	fn church_addition() {
		assert_eq!(normalize(plus().app(one())), succ()); // PLUS 1 → SUCC

		assert_eq!(normalize(plus().app(zero()).app(zero())), zero());
		assert_eq!(normalize(plus().app(zero()).app(one())),  one());
		assert_eq!(normalize(plus().app(one()).app(zero())),  one());
		assert_eq!(normalize(plus().app(one()).app(one())),   to_cnum(2));

		assert_eq!(normalize(plus().app(to_cnum(2)).app(to_cnum(3))), to_cnum(5));
		assert_eq!(normalize(plus().app(to_cnum(4)).app(to_cnum(4))), to_cnum(8));
	}

	#[test]
	fn church_multiplication() {
		assert_eq!(normalize(mult().app(to_cnum(3)).app(to_cnum(4))), to_cnum(12));
		assert_eq!(normalize(mult().app(to_cnum(1)).app(to_cnum(3))), to_cnum(3));
		assert_eq!(normalize(mult().app(to_cnum(5)).app(to_cnum(0))), to_cnum(0));
	}

	#[test]
	fn church_exponentiation() {
		assert_eq!(normalize(pow().app(to_cnum(2)).app(to_cnum(4))), to_cnum(16));
		assert_eq!(normalize(pow().app(to_cnum(1)).app(to_cnum(6))), to_cnum(1));
		assert_eq!(normalize(pow().app(to_cnum(3)).app(to_cnum(2))), to_cnum(9));
		assert_eq!(normalize(pow().app(to_cnum(4)).app(to_cnum(1))), to_cnum(4));
//		assert_eq!(normalize(pow().app(to_cnum(5)).app(zero())),	 to_cnum(1)); // n^0 fails - why?
	}

	#[test]
	fn church_subtraction() {
		assert_eq!(normalize(sub().app(zero()).app(zero())),	zero());
		assert_eq!(normalize(sub().app(zero()).app(one())),		zero());
		assert_eq!(normalize(sub().app(one()).app(zero())),		one());
		assert_eq!(normalize(sub().app(to_cnum(2)).app(one())), one());

		assert_eq!(normalize(sub().app(to_cnum(5)).app(to_cnum(3))), to_cnum(2));
		assert_eq!(normalize(sub().app(to_cnum(8)).app(to_cnum(4))), to_cnum(4));
	}

	#[test]
	fn church_predecessor() {
		assert_eq!(normalize(pred().app(zero())), zero());
		assert_eq!(normalize(pred().app(one())), zero());
		assert_eq!(normalize(pred().app(to_cnum(5))), to_cnum(4));
	}

	#[test]
	fn church_comparison() {
		assert_eq!(normalize(lt().app(zero()).app(zero())), fls());
		assert_eq!(normalize(lt().app(one()).app(zero())),  fls());
		assert_eq!(normalize(lt().app(zero()).app(one())),  tru());

		assert_eq!(normalize(leq().app(zero()).app(zero())), tru());
		assert_eq!(normalize(leq().app(zero()).app(one())),  tru());
		assert_eq!(normalize(leq().app(one()).app(zero())),  fls());

		assert_eq!(normalize(eq().app(zero()).app(zero())), tru());
		assert_eq!(normalize(eq().app(zero()).app(one())),  fls());
		assert_eq!(normalize(eq().app(one()).app(zero())),  fls());
		// TODO: add lt, gt, geq
	}
}
<commit_msg>Add NEQ, split some long functions<commit_after>//! [Church-encoded numerals](https://en.wikipedia.org/wiki/Church_encoding#Church_numerals)

use term::*;
use term::Term::*;
use term::Error::*;
use booleans::*;

/// Produces a Church-encoded zero.
///
/// ZERO := λfx.x = λ λ 1
/// # Example
///
/// ```
/// use lambda_calculus::arithmetic::zero;
///
/// assert_eq!(format!("{}", zero()), "λλ1");
/// ```
pub fn zero() -> Term { abs(abs(Var(1))) }

/// Applied to a Church-encoded number it produces a Church-encoded boolean, indicating whether its
/// argument is equal to zero.
///
/// IS_ZERO := λn.n (λx.FALSE) TRUE =  λ 1 (λ FALSE) TRUE
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, is_zero};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(is_zero().app(zero())), tru());
/// ```
pub fn is_zero() -> Term { abs(Var(1).app(abs(fls())).app(tru())) }

/// Produces a Church-encoded one.
///
/// ONE := λfx.f x = λ λ 2 1
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::one;
///
/// assert_eq!(format!("{}", one()), "λλ21");
/// ```
pub fn one() -> Term { abs(abs(Var(2).app(Var(1)))) }

/// Applied to a Church-encoded number it produces its successor.
///
/// SUCC := λnfx.f (n f x) = λ λ λ 2 (3 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, succ};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(succ().app(zero())), one());
/// ```
pub fn succ() -> Term { abs(abs(abs(Var(2).app(Var(3).app(Var(2)).app(Var(1)))))) }

/// Applied to two Church-encoded numbers it produces their sum.
///
/// PLUS := λmnfx.m f (n f x) = λ λ λ λ 4 2 (3 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, plus};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(plus().app(zero()).app(one())), one());
/// ```
pub fn plus() -> Term { abs(abs(abs(abs(Var(4).app(Var(2)).app(Var(3).app(Var(2)).app(Var(1))))))) }

/// Applied to two Church-encoded numbers it produces their product.
///
/// MULT := λmnf.m (n f) = λ λ λ 3 (2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, mult};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(mult().app(one()).app(one())), one());
/// ```
pub fn mult() -> Term { abs(abs(abs(Var(3).app(Var(2).app(Var(1)))))) }

/// Applied to two Church-encoded numbers it raises the first one to the power of the second one.
///
/// POW := λbe.e b = λ λ 1 2
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, pow};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(pow().app(one()).app(one())), one());
/// ```
pub fn pow() -> Term { abs(abs(Var(1).app(Var(2)))) }

/// Applied to a Church-encoded number it produces its predecessor.
///
/// PRED := λnfx.n (λgh.h (g f)) (λu.x) (λu.u) = λ λ λ 3 (λ λ 1 (2 4)) (λ 2) (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, pred};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(pred().app(one())), zero());
/// ```
pub fn pred() -> Term {
	abs(abs(abs(
		Var(3)
		.app(abs(abs(Var(1).app(Var(2).app(Var(4))))))
		.app(abs(Var(2)))
		.app(abs(Var(1)))
	)))
}

/// Applied to two Church-encoded numbers it subtracts the second one from the first one.
///
/// SUB := λmn.n PRED m = λ λ 1 PRED 2
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, sub};
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(sub().app(one()).app(zero())), one());
/// ```
pub fn sub() -> Term { abs(abs(Var(1).app(pred()).app(Var(2)))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is less than the second one.
///
/// LT := λab.NOT (LEQ b a) = λ λ NOT (LEQ 1 2)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, lt};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(lt().app(zero()).app(one())), tru());
/// ```
pub fn lt() -> Term { abs(abs(not().app(leq().app(Var(1)).app(Var(2))))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is less or egual to the second one.
///
/// LEQ := λmn.IS_ZERO (SUB m n) = λ λ IS_ZERO (SUB 2 1)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{zero, one, leq};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(leq().app(zero()).app(one())), tru());
/// ```
pub fn leq() -> Term { abs(abs(is_zero().app(sub().app(Var(2)).app(Var(1))))) }

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is egual to the second one.
///
/// EQ := λmn.AND (LEQ m n) (LEQ n m) = λ λ AND (LEQ 2 1) (LEQ 1 2)
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, eq};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(eq().app(one()).app(one())), tru());
/// ```
pub fn eq() -> Term {
	abs(abs(
		and()
		.app(leq().app(Var(2)).app(Var(1)))
		.app(leq().app(Var(1)).app(Var(2)))
	))
}

/// Applied to two Church-encoded numbers it returns a Church-encoded boolean indicating whether its
/// first argument is not egual to the second one.
///
/// NEQ := λab.OR (NOT (LEQ a b)) (NOT (LEQ b a)) = λ λ OR (NOT (LEQ 2 1)) (NOT (LEQ 1 2))
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, neq};
/// use lambda_calculus::booleans::tru;
/// use lambda_calculus::reduction::normalize;
///
/// assert_eq!(normalize(neq().app(zero()).app(one())), tru());
/// ```
pub fn neq() -> Term {
	abs(abs(
		or()
		.app(not().app(leq().app(Var(2)).app(Var(1))))
		.app(not().app(leq().app(Var(1)).app(Var(2))))
	))
}

impl Term {
	/// Returns the value of a Church-encoded number.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::arithmetic::one;
	///
	/// assert_eq!(one().value(), Ok(1));
	/// ```
	pub fn value(&self) -> Result<usize, Error> {
		if let Ok(ref inner) = self.unabs_ref().and_then(|t| t.unabs_ref()) {
			Ok(try!(inner._value()))
		} else {
			Err(NotANum)
		}
	}

	fn _value(&self) -> Result<usize, Error> {
		if let Ok(ref rhs) = self.rhs_ref() {
			Ok(1 + try!(rhs._value()))
		} else if let Var(n) = *self {
			if n == 1 {
				Ok(0)
			} else {
				Err(NotANum)
			}
		} else {
			Err(NotANum)
		}
	}

	/// Checks whether a term is a Church-encoded number.
	///
	/// # Example
	/// ```
	/// use lambda_calculus::arithmetic::one;
	///
	/// assert!(one().is_number());
	/// ```
	pub fn is_number(&self) -> bool { self.value().is_ok() }
}

/// Produces a Church-encoded term with a value of the given natural number.
///
/// # Example
/// ```
/// use lambda_calculus::arithmetic::{one, to_cnum};
///
/// assert_eq!(to_cnum(1), one());
/// ```
pub fn to_cnum(n: usize) -> Term {
	let mut inner = Var(1);
	let mut count = n;

	while count > 0 {
		inner = Var(2).app(inner);
		count -= 1;
	}

	abs(abs(inner))
}

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

	#[test]
	fn church_zero() {
		assert_eq!(normalize(is_zero().app(zero())), tru());
		assert_eq!(normalize(is_zero().app(one())), fls());
	}

	#[test]
	fn church_successor() {
		assert_eq!(normalize(succ().app(zero())), one());
		assert_eq!(normalize(succ().app(one())), abs(abs(Var(2).app(Var(2).app(Var(1))))));
		assert_eq!(normalize(succ().app(succ().app(succ().app(zero())))), abs(abs(Var(2).app(Var(2).app(Var(2).app(Var(1)))))));
	}

	#[test]
	fn church_number_identification() {
		for n in 0..5 { assert!(to_cnum(n).is_number()) }
	}

	#[test]
	fn church_number_creation() {
		assert_eq!(to_cnum(0), zero());
		assert_eq!(to_cnum(1), one());
		assert_eq!(to_cnum(2), normalize(succ().app(one())));
	}

	#[test]
	fn church_number_values() {
		for n in 0..10 { assert_eq!(to_cnum(n).value(), Ok(n)) }

		assert_eq!(tru().value(),		Err(NotANum));
		assert_eq!(Var(1).value(),		Err(NotANum));
		assert_eq!(abs(Var(1)).value(),	Err(NotANum));
	}

	#[test]
	fn church_addition() {
		assert_eq!(normalize(plus().app(one())), succ()); // PLUS 1 → SUCC

		assert_eq!(normalize(plus().app(zero()).app(zero())), zero());
		assert_eq!(normalize(plus().app(zero()).app(one())),  one());
		assert_eq!(normalize(plus().app(one()).app(zero())),  one());
		assert_eq!(normalize(plus().app(one()).app(one())),   to_cnum(2));

		assert_eq!(normalize(plus().app(to_cnum(2)).app(to_cnum(3))), to_cnum(5));
		assert_eq!(normalize(plus().app(to_cnum(4)).app(to_cnum(4))), to_cnum(8));
	}

	#[test]
	fn church_multiplication() {
		assert_eq!(normalize(mult().app(to_cnum(3)).app(to_cnum(4))), to_cnum(12));
		assert_eq!(normalize(mult().app(to_cnum(1)).app(to_cnum(3))), to_cnum(3));
		assert_eq!(normalize(mult().app(to_cnum(5)).app(to_cnum(0))), to_cnum(0));
	}

	#[test]
	fn church_exponentiation() {
		assert_eq!(normalize(pow().app(to_cnum(2)).app(to_cnum(4))), to_cnum(16));
		assert_eq!(normalize(pow().app(to_cnum(1)).app(to_cnum(6))), to_cnum(1));
		assert_eq!(normalize(pow().app(to_cnum(3)).app(to_cnum(2))), to_cnum(9));
		assert_eq!(normalize(pow().app(to_cnum(4)).app(to_cnum(1))), to_cnum(4));
//		assert_eq!(normalize(pow().app(to_cnum(5)).app(zero())),	 to_cnum(1)); // n^0 fails - why?
	}

	#[test]
	fn church_subtraction() {
		assert_eq!(normalize(sub().app(zero()).app(zero())),	zero());
		assert_eq!(normalize(sub().app(zero()).app(one())),		zero());
		assert_eq!(normalize(sub().app(one()).app(zero())),		one());
		assert_eq!(normalize(sub().app(to_cnum(2)).app(one())), one());

		assert_eq!(normalize(sub().app(to_cnum(5)).app(to_cnum(3))), to_cnum(2));
		assert_eq!(normalize(sub().app(to_cnum(8)).app(to_cnum(4))), to_cnum(4));
	}

	#[test]
	fn church_predecessor() {
		assert_eq!(normalize(pred().app(zero())), zero());
		assert_eq!(normalize(pred().app(one())), zero());
		assert_eq!(normalize(pred().app(to_cnum(5))), to_cnum(4));
	}

	#[test]
	fn church_comparisons() {
		assert_eq!(normalize(lt().app(zero()).app(zero())), fls());
		assert_eq!(normalize(lt().app(one()).app(zero())),  fls());
		assert_eq!(normalize(lt().app(zero()).app(one())),  tru());

		assert_eq!(normalize(leq().app(zero()).app(zero())), tru());
		assert_eq!(normalize(leq().app(zero()).app(one())),  tru());
		assert_eq!(normalize(leq().app(one()).app(zero())),  fls());

		assert_eq!(normalize(eq().app(zero()).app(zero())), tru());
		assert_eq!(normalize(eq().app(zero()).app(one())),  fls());
		assert_eq!(normalize(eq().app(one()).app(zero())),  fls());

		assert_eq!(normalize(neq().app(zero()).app(zero())), fls());
		assert_eq!(normalize(neq().app(zero()).app(one())),  tru());
		assert_eq!(normalize(neq().app(one()).app(zero())),  tru());
		// TODO: add gt, geq
	}
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// spell-checker:ignore (acronyms/names) Gehring
// spell-checker:ignore (rustlang) clippy concat rustlang
// spell-checker:ignore (uutils) coreutils uucore uumain uutils sigpipe
// spell-checker:ignore (shell) busybox

include!(concat!(env!("OUT_DIR"), "/uutils_crates.rs"));

extern crate lazy_static;
extern crate uucore;

use lazy_static::lazy_static;
use std::collections::hash_map::HashMap;
use std::io::Write;

static VERSION: &str = env!("CARGO_PKG_VERSION");

lazy_static! {
    static ref BINARY_PATH: std::path::PathBuf = std::env::current_exe().unwrap();
    static ref NAME: &'static str = &*BINARY_PATH.file_stem().unwrap().to_str().unwrap();
}

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn usage(utils: &UtilityMap) {
    println!("{} {}", *NAME, VERSION);
    println!();
    println!("Usage:");
    println!("  {} [util [arguments...]]\n", *NAME);
    println!("Currently defined functions:");
    #[allow(clippy::map_clone)]
    let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils {
        println!("\t{}", util);
    }
}

fn main() {
    uucore::panic::install_sigpipe_hook();

    let utils = util_map();
    let mut args: Vec<String> = uucore::args().collect();

    let binary = &BINARY_PATH;
    let binary_as_util = binary.file_stem().unwrap().to_str().unwrap();

    // binary name equals util name?
    if let Some(&uumain) = utils.get(binary_as_util) {
        std::process::exit(uumain(args));
    }

    // binary name equals prefixed util name?
    // * prefix/stem may be any string ending in a non-alphanumeric character
    if let Some(util) = utils.keys().find(|util| {
        binary_as_util.ends_with(*util)
            && !(&binary_as_util[..binary_as_util.len() - (*util).len()])
                .ends_with(char::is_alphanumeric)
    }) {
        // prefixed util => replace 0th (aka, executable name) argument
        args[0] = (*util).to_owned();
    } else {
        // unmatched binary name => regard as multi-binary container and advance argument list
        args.remove(0);
    }

    // 0th argument equals util name?
    if !args.is_empty() {
        let util = &args[0][..];

        match utils.get(util) {
            Some(&uumain) => {
                std::process::exit(uumain(args.clone()));
            }
            None => {
                if &args[0][..] == "--help" || &args[0][..] == "-h" {
                    // see if they want help on a specific util
                    if args.len() >= 2 {
                        let util = &args[1][..];
                        match utils.get(util) {
                            Some(&uumain) => {
                                let code = uumain(vec![util.to_owned(), "--help".to_owned()]);
                                std::io::stdout().flush().expect("could not flush stdout");
                                std::process::exit(code);
                            }
                            None => {
                                println!("{}: applet not found", util);
                                std::process::exit(1);
                            }
                        }
                    }
                    usage(&utils);
                    std::process::exit(0);
                } else {
                    println!("{}: applet not found", util);
                    std::process::exit(1);
                }
            }
        }
    } else {
        // no arguments provided
        usage(&utils);
        std::process::exit(0);
    }
}
<commit_msg>fix/uutils ~ support function/util (aka, applet) symlink aliasing where possible<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Michael Gehring <mg@ebfe.org>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// spell-checker:ignore (acronyms/names) Gehring
// spell-checker:ignore (rustlang) clippy concat rustlang
// spell-checker:ignore (uutils) coreutils uucore uumain uutils sigpipe
// spell-checker:ignore (shell) busybox symlinks

include!(concat!(env!("OUT_DIR"), "/uutils_crates.rs"));

extern crate lazy_static;
extern crate uucore;

use lazy_static::lazy_static;
use std::collections::hash_map::HashMap;
use std::io::Write;

static VERSION: &str = env!("CARGO_PKG_VERSION");

lazy_static! {
    static ref BINARY_PATH: std::path::PathBuf = {
        // support symlinks by using args[0], when possible, with fallback to current_exe()
        match std::env::args().next() {
            Some(ref s) if !s.is_empty() => std::path::PathBuf::from(s),
            _ => std::env::current_exe().unwrap(),
        }
    };
    static ref NAME: &'static str = &*BINARY_PATH.file_stem().unwrap().to_str().unwrap();
}

include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));

fn usage(utils: &UtilityMap) {
    println!("{} {}", *NAME, VERSION);
    println!();
    println!("Usage:");
    println!("  {} [util [arguments...]]\n", *NAME);
    println!("Currently defined functions:");
    #[allow(clippy::map_clone)]
    let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
    utils.sort();
    for util in utils {
        println!("\t{}", util);
    }
}

fn main() {
    uucore::panic::install_sigpipe_hook();

    let utils = util_map();
    let mut args: Vec<String> = uucore::args().collect();

    let binary = &BINARY_PATH;
    let binary_as_util = binary.file_stem().unwrap().to_str().unwrap();

    // binary name equals util name?
    if let Some(&uumain) = utils.get(binary_as_util) {
        std::process::exit(uumain(args));
    }

    // binary name equals prefixed util name?
    // * prefix/stem may be any string ending in a non-alphanumeric character
    if let Some(util) = utils.keys().find(|util| {
        binary_as_util.ends_with(*util)
            && !(&binary_as_util[..binary_as_util.len() - (*util).len()])
                .ends_with(char::is_alphanumeric)
    }) {
        // prefixed util => replace 0th (aka, executable name) argument
        args[0] = (*util).to_owned();
    } else {
        // unmatched binary name => regard as multi-binary container and advance argument list
        args.remove(0);
    }

    // 0th argument equals util name?
    if !args.is_empty() {
        let util = &args[0][..];

        match utils.get(util) {
            Some(&uumain) => {
                std::process::exit(uumain(args.clone()));
            }
            None => {
                if &args[0][..] == "--help" || &args[0][..] == "-h" {
                    // see if they want help on a specific util
                    if args.len() >= 2 {
                        let util = &args[1][..];
                        match utils.get(util) {
                            Some(&uumain) => {
                                let code = uumain(vec![util.to_owned(), "--help".to_owned()]);
                                std::io::stdout().flush().expect("could not flush stdout");
                                std::process::exit(code);
                            }
                            None => {
                                println!("{}: applet not found", util);
                                std::process::exit(1);
                            }
                        }
                    }
                    usage(&utils);
                    std::process::exit(0);
                } else {
                    println!("{}: applet not found", util);
                    std::process::exit(1);
                }
            }
        }
    } else {
        // no arguments provided
        usage(&utils);
        std::process::exit(0);
    }
}
<|endoftext|>


<commit_before>#![cfg(target_arch = "x86_64")]

use crate::structures::paging::{frame::PhysFrame, mapper::*, page_table::PageTable};

/// A Mapper implementation that requires that the complete physically memory is mapped at some
/// offset in the virtual address space.
#[derive(Debug)]
pub struct OffsetPageTable<'a> {
    inner: MappedPageTable<'a, PhysOffset>,
}

impl<'a> OffsetPageTable<'a> {
    /// Creates a new `OffsetPageTable` that uses the given offset for converting virtual
    /// to physical addresses.
    ///
    /// This function is unsafe because the caller must guarantee that the passed `phys_offset`
    /// is correct. Also, the passed `level_4_table` must point to the level 4 page table
    /// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g.
    /// by writing to an illegal memory location.
    pub unsafe fn new(level_4_table: &'a mut PageTable, phys_offset: u64) -> Self {
        let phys_offset = PhysOffset {
            offset: phys_offset,
        };
        Self {
            inner: MappedPageTable::new(level_4_table, phys_offset),
        }
    }
}

#[derive(Debug)]
struct PhysOffset {
    offset: u64,
}

impl PhysToVirt for PhysOffset {
    fn phys_to_virt(&self, frame: PhysFrame) -> *mut PageTable {
        let phys = frame.start_address().as_u64();
        let virt = VirtAddr::new(phys + self.offset);
        virt.as_mut_ptr()
    }
}

// delegate all trait implementations to inner

impl<'a> Mapper<Size1GiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size1GiB>,
        frame: PhysFrame<Size1GiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size1GiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size1GiB>,
    ) -> Result<(PhysFrame<Size1GiB>, MapperFlush<Size1GiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size1GiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> Mapper<Size2MiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size2MiB>,
        frame: PhysFrame<Size2MiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size2MiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size2MiB>,
    ) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size2MiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> Mapper<Size4KiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size4KiB>,
        frame: PhysFrame<Size4KiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size4KiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size4KiB>,
    ) -> Result<(PhysFrame<Size4KiB>, MapperFlush<Size4KiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size4KiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> MapperAllSizes for OffsetPageTable<'a> {
    fn translate(&self, addr: VirtAddr) -> TranslateResult {
        self.inner.translate(addr)
    }
}
<commit_msg>Change phys_offset type to VirtAddr<commit_after>#![cfg(target_arch = "x86_64")]

use crate::structures::paging::{frame::PhysFrame, mapper::*, page_table::PageTable};

/// A Mapper implementation that requires that the complete physically memory is mapped at some
/// offset in the virtual address space.
#[derive(Debug)]
pub struct OffsetPageTable<'a> {
    inner: MappedPageTable<'a, PhysOffset>,
}

impl<'a> OffsetPageTable<'a> {
    /// Creates a new `OffsetPageTable` that uses the given offset for converting virtual
    /// to physical addresses.
    ///
    /// This function is unsafe because the caller must guarantee that the passed `phys_offset`
    /// is correct. Also, the passed `level_4_table` must point to the level 4 page table
    /// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g.
    /// by writing to an illegal memory location.
    pub unsafe fn new(level_4_table: &'a mut PageTable, phys_offset: VirtAddr) -> Self {
        let phys_offset = PhysOffset {
            offset: phys_offset,
        };
        Self {
            inner: MappedPageTable::new(level_4_table, phys_offset),
        }
    }
}

#[derive(Debug)]
struct PhysOffset {
    offset: VirtAddr,
}

impl PhysToVirt for PhysOffset {
    fn phys_to_virt(&self, frame: PhysFrame) -> *mut PageTable {
        let phys = frame.start_address().as_u64();
        let virt = self.offset + phys;
        virt.as_mut_ptr()
    }
}

// delegate all trait implementations to inner

impl<'a> Mapper<Size1GiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size1GiB>,
        frame: PhysFrame<Size1GiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size1GiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size1GiB>,
    ) -> Result<(PhysFrame<Size1GiB>, MapperFlush<Size1GiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size1GiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size1GiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size1GiB>) -> Result<PhysFrame<Size1GiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> Mapper<Size2MiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size2MiB>,
        frame: PhysFrame<Size2MiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size2MiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size2MiB>,
    ) -> Result<(PhysFrame<Size2MiB>, MapperFlush<Size2MiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size2MiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size2MiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size2MiB>) -> Result<PhysFrame<Size2MiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> Mapper<Size4KiB> for OffsetPageTable<'a> {
    unsafe fn map_to<A>(
        &mut self,
        page: Page<Size4KiB>,
        frame: PhysFrame<Size4KiB>,
        flags: PageTableFlags,
        allocator: &mut A,
    ) -> Result<MapperFlush<Size4KiB>, MapToError>
    where
        A: FrameAllocator<Size4KiB>,
    {
        self.inner.map_to(page, frame, flags, allocator)
    }

    fn unmap(
        &mut self,
        page: Page<Size4KiB>,
    ) -> Result<(PhysFrame<Size4KiB>, MapperFlush<Size4KiB>), UnmapError> {
        self.inner.unmap(page)
    }

    fn update_flags(
        &mut self,
        page: Page<Size4KiB>,
        flags: PageTableFlags,
    ) -> Result<MapperFlush<Size4KiB>, FlagUpdateError> {
        self.inner.update_flags(page, flags)
    }

    fn translate_page(&self, page: Page<Size4KiB>) -> Result<PhysFrame<Size4KiB>, TranslateError> {
        self.inner.translate_page(page)
    }
}

impl<'a> MapperAllSizes for OffsetPageTable<'a> {
    fn translate(&self, addr: VirtAddr) -> TranslateResult {
        self.inner.translate(addr)
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Algebraic Data Type (ADT) `GridVariant` use case using Rust `enum`
// should be more robust than `std::Any`

#![feature(plugin)]
#![plugin(docopt_macros)]
#![feature(custom_derive)]

extern crate rustc_serialize;
extern crate docopt;
extern crate num;

use docopt::Docopt;
use std::io;
use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use std::mem;
use std::iter::FromIterator;

extern crate endianness;
use endianness::{ByteOrder, read_u32, read_f32, read_f64};
use num::Num;

use std::fmt::Debug;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

struct Grid<T> {
    points: Vec<Vec<T>>,
}

#[derive(Debug)]
enum GridType { f32_t, f64_t, c32_t, c64_t, }

enum GridVariant {
    Grid_f32(Box<Grid<f32>>),
    Grid_f64(Box<Grid<f64>>),
    Grid_c32(Box<Grid<c32>>),
    Grid_c64(Box<Grid<c64>>),
}

trait GridTrait<T> {
    // a constructor
    fn new() -> Grid<T> { Grid {points: Vec::new() } }

    // unformatted read from the buffer
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>);
}

impl GridTrait<f32> for Grid<f32> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f32>();
                let val = read_f32(&grid_buf[start .. ], byte_order);
                val.unwrap()
            }))
        }));
    }
}

impl GridTrait<c32> for Grid<c32> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start_1 = (i * ysize + j) * 2 * mem::size_of::<f32>();
                let start_2 = start_1 + mem::size_of::<f32>(); // next f32 number
                let (real, imag) =
                    (read_f32(&grid_buf[start_1 .. ], byte_order),
                     read_f32(&grid_buf[start_2 .. ], byte_order));
                c32::new(real.unwrap(), imag.unwrap())
            }))
        }));
    }
}

impl GridTrait<f64> for Grid<f64> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f64>();
                let val = read_f64(&grid_buf[start .. ], byte_order);
                val.unwrap()
            }))
        }));
    }
}

// the Docopt usage string.
// https://github.com/docopt/docopt.rs
docopt!(Args derive Debug, "
Read grid gen.

Usage:
  gridgen read <file> [--verbose] [-d <dpath>]

Options:
  -h --help       Show this screen.
  -d --data-path  path to input data.
  --verbose       Be verbose.

");

fn read_from_file(namein: &String, data_path: &String, verbose: bool) -> Result<(ByteOrder, GridType, u32, u32, Vec<u8>), io::Error> {
    //let name = format!("{}/{}.bin", data_path, namein);
    let name = format!("{}/{}", data_path, namein);
    let mut try_open = File::open(name.clone());
    let mut file = match try_open {
        Ok(f) => f,
        Err(err) => {panic!("\"{}\" : {}\n",name, err)}
    };
    let mut buf = [0u8; 4];
    if verbose {
        println!("read from file: {}", name);
    }
    try!(file.read(&mut buf[0..1]));
    let is_big_endian = unsafe {mem::transmute::<[u8; 1], u8>([buf[0]])} == 1;
    let byte_order = if is_big_endian {ByteOrder::BigEndian} else {ByteOrder::LittleEndian};

    try!(file.read(&mut buf[..]));
    let prec = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let typ = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let xe = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let ye = read_u32(&buf[..], byte_order).unwrap();

    if verbose {
        println!("prec: {} (1 - Single Precision, 2 - Double Precision) typ: {} (1 - Real Values, 2 - Complex Values) xe: {} ye: {}",
                 prec, typ, xe, ye);
    }

    let (grid_type, grid_elem_size) =
        match (prec,typ) {
            (1,1) => (GridType::f32_t, mem::size_of::<f32>()),
            (1,2) => (GridType::c32_t, mem::size_of::<c32>()),
            (2,1) => (GridType::f64_t, mem::size_of::<f64>()),
            (2,2) => (GridType::c64_t, mem::size_of::<c64>()),
            (_,_) => panic!("illegal combination of prec: {} typ: {}", prec, typ)
        };
    let grid_sz = (xe * ye) as usize;
    let mut grid_buf = Vec::new();
    let sz = file.read_to_end(&mut grid_buf).unwrap();
    if sz != (grid_sz * grid_elem_size) {
        panic!("corrupted grid sz: {} xe*ye: {}", sz, xe * ye);
    }

    Ok((byte_order, grid_type, xe, ye, grid_buf))
}

fn dump_grid<T: std::fmt::Display>(grid_name: &str, grid: &Grid<T>) {
    println!("-I- dumping grid: {}", grid_name);
    let points = &grid.points;
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j] ; // as c64;
            println!("{} [{}][{}] = {:}", grid_name, i, j, p /*.to_string()*/);
        }
    }
}

fn count_nnz<T: Num>(grid: &Grid<T>) -> (usize, usize) {
    let points = &grid.points;
    let mut nnz = 0;
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j];
            if !p.is_zero() {
                nnz += 1;
            }
        }
    }
    (nnz, points.len() * points[0].len())
}

fn count_nnz_functional_way<T: Num>(grid: &Grid<T>) -> (usize, usize) {
    let points = &grid.points;
    let mut nnz = points.iter().fold(0, |sum, row| {
        let incr = {
            row.iter().fold(0, |c, v| if v.is_zero() {c} else {c+1} )
        };
        sum + incr
    } );
    (nnz, points.len() * points[0].len())
}

// bounding box indices for the grid
fn grid_bb_indices<T: Num>(grid: &Grid<T>) -> ((isize, isize), (isize, isize)) {
    let points = &grid.points;
    let ((mut llx,mut lly), (mut urx,mut ury)) =
        ((std::isize::MAX,std::isize::MAX),
         (std::isize::MIN,std::isize::MIN));
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j];
            if !p.is_zero() {
                let ii = i as isize;
                let jj = j as isize;
                if llx > ii { llx = ii; }
                if lly > jj { lly = jj; }
                if urx < ii { urx = ii; }
                if ury < jj { ury = jj; }
            }
        }
    }

    ((llx,lly), (urx,ury))
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    if args.flag_verbose {
        println!("{:?}", args);
        println!("input file name: {:?}", args.arg_file);
    }

    let fname = args.arg_file;
    let dpath = args.arg_dpath;
    let (byte_order, grid_type, xe, ye, grid_buf) = read_from_file(&fname, &dpath, args.flag_verbose).unwrap();

    let mut mask_grid =
        match grid_type {
            GridType::f32_t => {
                let mut f32_grid = Box::new(Grid::<f32>::new());
                (*f32_grid).read(byte_order, xe as usize, ye as usize, &grid_buf);
                GridVariant::Grid_f32(f32_grid)
            },
            GridType::c32_t => {
                let mut c32_grid = Box::new(Grid::<c32>::new());
                (*c32_grid).read(byte_order, xe as usize, ye as usize, &grid_buf);
                GridVariant::Grid_c32(c32_grid)
            },
            _ => panic!("not yet implemented for grid type: {:?}", grid_type)
        };

    match mask_grid {
        GridVariant::Grid_f32(agrid) => //dump_grid("f32_grid", &*agrid),
        {
          let (nnz, total) = count_nnz_functional_way(&*agrid);
          println!("nnz for f32 grid: {:} total: {:} ratio: {:.3}%",
                    nnz, total, (nnz as f64 / total as f64)* 100.0);
          let bb = grid_bb_indices(&*agrid);
          let ((llx,lly), (urx,ury)) = bb;
          println!("a bounding box indices for the grid mask: {:?} x_extent: {:} y_extent: {:}",
                   bb, urx-llx, ury-lly);
        }

        GridVariant::Grid_c32(agrid) => dump_grid("c32_grid", &*agrid),
        _ => panic!("not yet implemented")
    }

}
<commit_msg>implemented `write_asy` for adt_enum.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 Alexander Samoilov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Algebraic Data Type (ADT) `GridVariant` use case using Rust `enum`
// should be more robust than `std::Any`

#![feature(plugin)]
#![plugin(docopt_macros)]
#![feature(custom_derive)]

extern crate rustc_serialize;
extern crate docopt;
extern crate num;

use docopt::Docopt;
use std::io;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::io::Cursor;
use std::mem;
use std::iter::FromIterator;

extern crate endianness;
use endianness::{ByteOrder, read_u32, read_f32, read_f64};
use num::Num;

use std::fmt::Debug;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

struct Grid<T> {
    points: Vec<Vec<T>>,
}

#[derive(Debug)]
enum GridType { f32_t, f64_t, c32_t, c64_t, }

enum GridVariant {
    Grid_f32(Box<Grid<f32>>),
    Grid_f64(Box<Grid<f64>>),
    Grid_c32(Box<Grid<c32>>),
    Grid_c64(Box<Grid<c64>>),
}

trait GridTrait<T> {
    // a constructor
    fn new() -> Grid<T> { Grid {points: Vec::new() } }

    // unformatted read from the buffer
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>);
}

impl GridTrait<f32> for Grid<f32> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f32>();
                let val = read_f32(&grid_buf[start .. ], byte_order);
                val.unwrap()
            }))
        }));
    }
}

impl GridTrait<c32> for Grid<c32> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start_1 = (i * ysize + j) * 2 * mem::size_of::<f32>();
                let start_2 = start_1 + mem::size_of::<f32>(); // next f32 number
                let (real, imag) =
                    (read_f32(&grid_buf[start_1 .. ], byte_order),
                     read_f32(&grid_buf[start_2 .. ], byte_order));
                c32::new(real.unwrap(), imag.unwrap())
            }))
        }));
    }
}

impl GridTrait<f64> for Grid<f64> {
    fn read(&mut self,
            byte_order: ByteOrder,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f64>();
                let val = read_f64(&grid_buf[start .. ], byte_order);
                val.unwrap()
            }))
        }));
    }
}

// the Docopt usage string.
// https://github.com/docopt/docopt.rs
docopt!(Args derive Debug, "
Read grid gen.

Usage:
  gridgen read <file> [--verbose] [-d <dpath>] [-o <asy-file-name>]

Options:
  -h --help       Show this screen.
  -d --data-path  path to input data.
  -o --out-asy    name of output asy file.
  --verbose       Be verbose.

");

fn read_from_file(namein: &String, data_path: &String, verbose: bool) -> Result<(ByteOrder, GridType, u32, u32, Vec<u8>), io::Error> {
    //let name = format!("{}/{}.bin", data_path, namein);
    let name = format!("{}/{}", data_path, namein);
    let mut try_open = File::open(name.clone());
    let mut file = match try_open {
        Ok(f) => f,
        Err(err) => {panic!("\"{}\" : {}\n",name, err)}
    };
    let mut buf = [0u8; 4];
    if verbose {
        println!("read from file: {}", name);
    }
    try!(file.read(&mut buf[0..1]));
    let is_big_endian = unsafe {mem::transmute::<[u8; 1], u8>([buf[0]])} == 1;
    let byte_order = if is_big_endian {ByteOrder::BigEndian} else {ByteOrder::LittleEndian};

    try!(file.read(&mut buf[..]));
    let prec = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let typ = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let xe = read_u32(&buf[..], byte_order).unwrap();

    try!(file.read(&mut buf[..]));
    let ye = read_u32(&buf[..], byte_order).unwrap();

    if verbose {
        println!("prec: {} (1 - Single Precision, 2 - Double Precision) typ: {} (1 - Real Values, 2 - Complex Values) xe: {} ye: {}",
                 prec, typ, xe, ye);
    }

    let (grid_type, grid_elem_size) =
        match (prec,typ) {
            (1,1) => (GridType::f32_t, mem::size_of::<f32>()),
            (1,2) => (GridType::c32_t, mem::size_of::<c32>()),
            (2,1) => (GridType::f64_t, mem::size_of::<f64>()),
            (2,2) => (GridType::c64_t, mem::size_of::<c64>()),
            (_,_) => panic!("illegal combination of prec: {} typ: {}", prec, typ)
        };
    let grid_sz = (xe * ye) as usize;
    let mut grid_buf = Vec::new();
    let sz = file.read_to_end(&mut grid_buf).unwrap();
    if sz != (grid_sz * grid_elem_size) {
        panic!("corrupted grid sz: {} xe*ye: {}", sz, xe * ye);
    }

    Ok((byte_order, grid_type, xe, ye, grid_buf))
}

fn dump_grid<T: std::fmt::Display>(grid_name: &str, grid: &Grid<T>) {
    println!("-I- dumping grid: {}", grid_name);
    let points = &grid.points;
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j] ; // as c64;
            println!("{} [{}][{}] = {:}", grid_name, i, j, p /*.to_string()*/);
        }
    }
}

fn count_nnz<T: Num>(grid: &Grid<T>) -> (usize, usize) {
    let points = &grid.points;
    let mut nnz = 0;
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j];
            if !p.is_zero() {
                nnz += 1;
            }
        }
    }
    (nnz, points.len() * points[0].len())
}

fn count_nnz_functional_way<T: Num>(grid: &Grid<T>) -> (usize, usize) {
    let points = &grid.points;
    let mut nnz = points.iter().fold(0, |sum, row| {
        let incr = {
            row.iter().fold(0, |c, v| if v.is_zero() {c} else {c+1} )
        };
        sum + incr
    } );
    (nnz, points.len() * points[0].len())
}

// bounding box indices for the grid
fn grid_bb_indices<T: Num>(grid: &Grid<T>) -> ((isize, isize), (isize, isize)) {
    let points = &grid.points;
    let ((mut llx,mut lly), (mut urx,mut ury)) =
        ((std::isize::MAX,std::isize::MAX),
         (std::isize::MIN,std::isize::MIN));
    for i in 0 .. points.len() {
        let row = &points[i];
        for j in 0 .. row.len() {
            let p = &points[i][j];
            if !p.is_zero() {
                let ii = i as isize;
                let jj = j as isize;
                if llx > ii { llx = ii; }
                if lly > jj { lly = jj; }
                if urx < ii { urx = ii; }
                if ury < jj { ury = jj; }
            }
        }
    }

    ((llx,lly), (urx,ury))
}

fn write_asy<T: Num+std::fmt::Display>(fname: &str,
                     bounding_box: ((usize,usize), (usize,usize)),
                     grid: &Grid<T>) -> Result<(), io::Error> {
    const delta : usize = 10;
    let ((llx,lly), (urx,ury)) = bounding_box;
    let mut f = try!(File::create(fname));
    try!(write!(f, "size({},{});\n", (urx-llx)*delta, (ury-lly)*delta));
    try!(f.write(br#"
void draw_grid_cell(pair lb, pair ru, pen p = defaultpen())
{
  path r = lb -- (ru.x, lb.y) -- ru -- (lb.x, ru.y) -- cycle;
  filldraw(r, p);
}
"#));

    let points = &grid.points;
    for i in llx .. urx {
        for j in lly .. ury {
            let p = &points[i][j];
            if !p.is_zero() {
                let lb = (i    *delta, j    *delta);
                let ru = ((i+1)*delta, (j+1)*delta);
                try!(write!(f, "draw_grid_cell({:?}, {:?}, gray*{});\n", lb, ru, p));
            }
        }
    }

    Ok(())
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    if args.flag_verbose {
        println!("{:?}", args);
        println!("input file name: {:?}", args.arg_file);
    }

    let fname = args.arg_file;
    let dpath = args.arg_dpath;
    let asy_fname = if args.arg_asy_file_name != "" { args.arg_asy_file_name } else { format!("{}.asy", fname) };
    let (byte_order, grid_type, xe, ye, grid_buf) = read_from_file(&fname, &dpath, args.flag_verbose).unwrap();

    let mut mask_grid =
        match grid_type {
            GridType::f32_t => {
                let mut f32_grid = Box::new(Grid::<f32>::new());
                (*f32_grid).read(byte_order, xe as usize, ye as usize, &grid_buf);
                GridVariant::Grid_f32(f32_grid)
            },
            GridType::c32_t => {
                let mut c32_grid = Box::new(Grid::<c32>::new());
                (*c32_grid).read(byte_order, xe as usize, ye as usize, &grid_buf);
                GridVariant::Grid_c32(c32_grid)
            },
            _ => panic!("not yet implemented for grid type: {:?}", grid_type)
        };

    match mask_grid {
        GridVariant::Grid_f32(agrid) => //dump_grid("f32_grid", &*agrid),
        {
          let (nnz, total) = count_nnz_functional_way(&*agrid);
          println!("nnz for f32 grid: {:} total: {:} ratio: {:.3}%",
                    nnz, total, (nnz as f64 / total as f64)* 100.0);
          let bb = grid_bb_indices(&*agrid);
          let ((llx,lly), (urx,ury)) = bb;
          let (x_extent, y_extent) = (urx-llx, ury-lly);
          println!("a bounding box indices for the grid mask: {:?} x_extent: {:} y_extent: {:}",
                   bb, x_extent, y_extent);
          let halo = 10;
          //write_asy(&asy_fname,
          //          ( ((llx - halo) as usize, (lly - halo) as usize),
          //            ((urx + halo) as usize, (ury + halo) as usize) ),
          //          &*agrid);
          write_asy(&asy_fname,
                    ( ( (llx - halo)         as usize, (lly - halo)         as usize),
                      ( (llx + x_extent / 8) as usize, (lly + y_extent / 8) as usize) ),
                    &*agrid);
        }

        GridVariant::Grid_c32(agrid) => dump_grid("c32_grid", &*agrid),
        _ => panic!("not yet implemented")
    }

}
<|endoftext|>


<commit_before>extern crate fst;
extern crate ra_editor;
extern crate ra_syntax;
extern crate rayon;
extern crate relative_path;
extern crate rustc_hash;
extern crate salsa;

mod completion;
mod db;
mod descriptors;
mod imp;
mod input;
pub mod mock_analysis;
mod symbol_index;
mod syntax_ptr;

use std::{fmt, sync::Arc};

use ra_syntax::{AtomEdit, File, TextRange, TextUnit};
use rayon::prelude::*;
use relative_path::RelativePathBuf;

use crate::{
    imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
    symbol_index::SymbolIndex,
};

pub use crate::{
    completion::CompletionItem,
    descriptors::function::FnDescriptor,
    input::{CrateGraph, CrateId, FileId, FileResolver},
};
pub use ra_editor::{
    FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Canceled;

pub type Cancelable<T> = Result<T, Canceled>;

impl std::fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fmt.write_str("Canceled")
    }
}

impl std::error::Error for Canceled {}

#[derive(Default)]
pub struct AnalysisChange {
    files_added: Vec<(FileId, String)>,
    files_changed: Vec<(FileId, String)>,
    files_removed: Vec<(FileId)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
    file_resolver: Option<FileResolverImp>,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("files_added", &self.files_added.len())
            .field("files_changed", &self.files_changed.len())
            .field("files_removed", &self.files_removed.len())
            .field("libraries_added", &self.libraries_added.len())
            .field("crate_graph", &self.crate_graph)
            .field("file_resolver", &self.file_resolver)
            .finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }
    pub fn add_file(&mut self, file_id: FileId, text: String) {
        self.files_added.push((file_id, text))
    }
    pub fn change_file(&mut self, file_id: FileId, new_text: String) {
        self.files_changed.push((file_id, new_text))
    }
    pub fn remove_file(&mut self, file_id: FileId) {
        self.files_removed.push(file_id)
    }
    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }
    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
    pub fn set_file_resolver(&mut self, file_resolver: Arc<FileResolver>) {
        self.file_resolver = Some(FileResolverImp::new(file_resolver));
    }
}

#[derive(Debug)]
pub struct AnalysisHost {
    imp: AnalysisHostImpl,
}

impl AnalysisHost {
    pub fn new() -> AnalysisHost {
        AnalysisHost {
            imp: AnalysisHostImpl::new(),
        }
    }
    pub fn analysis(&self) -> Analysis {
        Analysis {
            imp: self.imp.analysis(),
        }
    }
    pub fn apply_change(&mut self, change: AnalysisChange) {
        self.imp.apply_change(change)
    }
}

#[derive(Debug)]
pub struct SourceChange {
    pub label: String,
    pub source_file_edits: Vec<SourceFileEdit>,
    pub file_system_edits: Vec<FileSystemEdit>,
    pub cursor_position: Option<Position>,
}

#[derive(Debug)]
pub struct Position {
    pub file_id: FileId,
    pub offset: TextUnit,
}

#[derive(Debug)]
pub struct SourceFileEdit {
    pub file_id: FileId,
    pub edits: Vec<AtomEdit>,
}

#[derive(Debug)]
pub enum FileSystemEdit {
    CreateFile {
        anchor: FileId,
        path: RelativePathBuf,
    },
    MoveFile {
        file: FileId,
        path: RelativePathBuf,
    },
}

#[derive(Debug)]
pub struct Diagnostic {
    pub message: String,
    pub range: TextRange,
    pub fix: Option<SourceChange>,
}

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            limit: usize::max_value(),
        }
    }
    pub fn only_types(&mut self) {
        self.only_types = true;
    }
    pub fn libs(&mut self) {
        self.libs = true;
    }
    pub fn exact(&mut self) {
        self.exact = true;
    }
    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

#[derive(Debug)]
pub struct Analysis {
    pub(crate) imp: AnalysisImpl,
}

impl Analysis {
    pub fn file_syntax(&self, file_id: FileId) -> File {
        self.imp.file_syntax(file_id).clone()
    }
    pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
        self.imp.file_line_index(file_id)
    }
    pub fn extend_selection(&self, file: &File, range: TextRange) -> TextRange {
        ra_editor::extend_selection(file, range).unwrap_or(range)
    }
    pub fn matching_brace(&self, file: &File, offset: TextUnit) -> Option<TextUnit> {
        ra_editor::matching_brace(file, offset)
    }
    pub fn syntax_tree(&self, file_id: FileId) -> String {
        let file = self.imp.file_syntax(file_id);
        ra_editor::syntax_tree(&file)
    }
    pub fn join_lines(&self, file_id: FileId, range: TextRange) -> SourceChange {
        let file = self.imp.file_syntax(file_id);
        SourceChange::from_local_edit(file_id, "join lines", ra_editor::join_lines(&file, range))
    }
    pub fn on_enter(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> {
        let file = self.imp.file_syntax(file_id);
        let edit = ra_editor::on_enter(&file, offset)?;
        let res = SourceChange::from_local_edit(file_id, "on enter", edit);
        Some(res)
    }
    pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> {
        let file = self.imp.file_syntax(file_id);
        Some(SourceChange::from_local_edit(
            file_id,
            "add semicolon",
            ra_editor::on_eq_typed(&file, offset)?,
        ))
    }
    pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
        let file = self.imp.file_syntax(file_id);
        ra_editor::file_structure(&file)
    }
    pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
        let file = self.imp.file_syntax(file_id);
        ra_editor::folding_ranges(&file)
    }
    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.world_symbols(query)
    }
    pub fn approximately_resolve_symbol(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.approximately_resolve_symbol(file_id, offset)
    }
    pub fn find_all_refs(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Vec<(FileId, TextRange)>> {
        Ok(self.imp.find_all_refs(file_id, offset))
    }
    pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.parent_module(file_id)
    }
    pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
        self.imp.crate_for(file_id)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
        Ok(self.imp.crate_root(crate_id))
    }
    pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
        let file = self.imp.file_syntax(file_id);
        Ok(ra_editor::runnables(&file))
    }
    pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
        let file = self.imp.file_syntax(file_id);
        Ok(ra_editor::highlight(&file))
    }
    pub fn completions(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Option<Vec<CompletionItem>>> {
        self.imp.completions(file_id, offset)
    }
    pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> {
        Ok(self.imp.assists(file_id, range))
    }
    pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
        self.imp.diagnostics(file_id)
    }
    pub fn resolve_callable(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> {
        self.imp.resolve_callable(file_id, offset)
    }
}

#[derive(Debug)]
pub struct LibraryData {
    files: Vec<(FileId, String)>,
    file_resolver: FileResolverImp,
    symbol_index: SymbolIndex,
}

impl LibraryData {
    pub fn prepare(files: Vec<(FileId, String)>, file_resolver: Arc<FileResolver>) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, text)| {
            let file = File::parse(text);
            (*file_id, file)
        }));
        LibraryData {
            files,
            file_resolver: FileResolverImp::new(file_resolver),
            symbol_index,
        }
    }
}

#[test]
fn analysis_is_send() {
    fn is_send<T: Send>() {}
    is_send::<Analysis>();
}
<commit_msg>Some docs<commit_after>//! ra_analyzer crate is the brain of Rust analyzer. It relies on the `salsa`
//! crate, which provides and incremental on-deman database of facts.

extern crate fst;
extern crate ra_editor;
extern crate ra_syntax;
extern crate rayon;
extern crate relative_path;
extern crate rustc_hash;
extern crate salsa;

mod completion;
mod db;
mod descriptors;
mod imp;
mod input;
pub mod mock_analysis;
mod symbol_index;
mod syntax_ptr;

use std::{fmt, sync::Arc};

use ra_syntax::{AtomEdit, File, TextRange, TextUnit};
use rayon::prelude::*;
use relative_path::RelativePathBuf;

use crate::{
    imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp},
    symbol_index::SymbolIndex,
};

pub use crate::{
    completion::CompletionItem,
    descriptors::function::FnDescriptor,
    input::{CrateGraph, CrateId, FileId, FileResolver},
};
pub use ra_editor::{
    FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Canceled;

pub type Cancelable<T> = Result<T, Canceled>;

impl std::fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fmt.write_str("Canceled")
    }
}

impl std::error::Error for Canceled {}

#[derive(Default)]
pub struct AnalysisChange {
    files_added: Vec<(FileId, String)>,
    files_changed: Vec<(FileId, String)>,
    files_removed: Vec<(FileId)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
    file_resolver: Option<FileResolverImp>,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("files_added", &self.files_added.len())
            .field("files_changed", &self.files_changed.len())
            .field("files_removed", &self.files_removed.len())
            .field("libraries_added", &self.libraries_added.len())
            .field("crate_graph", &self.crate_graph)
            .field("file_resolver", &self.file_resolver)
            .finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }
    pub fn add_file(&mut self, file_id: FileId, text: String) {
        self.files_added.push((file_id, text))
    }
    pub fn change_file(&mut self, file_id: FileId, new_text: String) {
        self.files_changed.push((file_id, new_text))
    }
    pub fn remove_file(&mut self, file_id: FileId) {
        self.files_removed.push(file_id)
    }
    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }
    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
    pub fn set_file_resolver(&mut self, file_resolver: Arc<FileResolver>) {
        self.file_resolver = Some(FileResolverImp::new(file_resolver));
    }
}

/// `AnalysisHost` stores the current state of the world.
#[derive(Debug)]
pub struct AnalysisHost {
    imp: AnalysisHostImpl,
}

impl AnalysisHost {
    pub fn new() -> AnalysisHost {
        AnalysisHost {
            imp: AnalysisHostImpl::new(),
        }
    }
    /// Returns a snapshot of the current state, which you can query for
    /// semantic information.
    pub fn analysis(&self) -> Analysis {
        Analysis {
            imp: self.imp.analysis(),
        }
    }
    /// Applies changes to the current state of the world. If there are
    /// outstanding snapshots, they will be canceled.
    pub fn apply_change(&mut self, change: AnalysisChange) {
        self.imp.apply_change(change)
    }
}

#[derive(Debug)]
pub struct SourceChange {
    pub label: String,
    pub source_file_edits: Vec<SourceFileEdit>,
    pub file_system_edits: Vec<FileSystemEdit>,
    pub cursor_position: Option<Position>,
}

#[derive(Debug)]
pub struct Position {
    pub file_id: FileId,
    pub offset: TextUnit,
}

#[derive(Debug)]
pub struct SourceFileEdit {
    pub file_id: FileId,
    pub edits: Vec<AtomEdit>,
}

#[derive(Debug)]
pub enum FileSystemEdit {
    CreateFile {
        anchor: FileId,
        path: RelativePathBuf,
    },
    MoveFile {
        file: FileId,
        path: RelativePathBuf,
    },
}

#[derive(Debug)]
pub struct Diagnostic {
    pub message: String,
    pub range: TextRange,
    pub fix: Option<SourceChange>,
}

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            limit: usize::max_value(),
        }
    }
    pub fn only_types(&mut self) {
        self.only_types = true;
    }
    pub fn libs(&mut self) {
        self.libs = true;
    }
    pub fn exact(&mut self) {
        self.exact = true;
    }
    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

/// Analysis is a snapshot of a world state at a moment in time. It is the main
/// entry point for asking semantic information about the world. When the world
/// state is advanced using `AnalysisHost::apply_change` method, all existing
/// `Analysis` are canceled (most method return `Err(Canceled)`).
#[derive(Debug)]
pub struct Analysis {
    pub(crate) imp: AnalysisImpl,
}

impl Analysis {
    pub fn file_syntax(&self, file_id: FileId) -> File {
        self.imp.file_syntax(file_id).clone()
    }
    pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
        self.imp.file_line_index(file_id)
    }
    pub fn extend_selection(&self, file: &File, range: TextRange) -> TextRange {
        ra_editor::extend_selection(file, range).unwrap_or(range)
    }
    pub fn matching_brace(&self, file: &File, offset: TextUnit) -> Option<TextUnit> {
        ra_editor::matching_brace(file, offset)
    }
    pub fn syntax_tree(&self, file_id: FileId) -> String {
        let file = self.imp.file_syntax(file_id);
        ra_editor::syntax_tree(&file)
    }
    pub fn join_lines(&self, file_id: FileId, range: TextRange) -> SourceChange {
        let file = self.imp.file_syntax(file_id);
        SourceChange::from_local_edit(file_id, "join lines", ra_editor::join_lines(&file, range))
    }
    pub fn on_enter(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> {
        let file = self.imp.file_syntax(file_id);
        let edit = ra_editor::on_enter(&file, offset)?;
        let res = SourceChange::from_local_edit(file_id, "on enter", edit);
        Some(res)
    }
    pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> {
        let file = self.imp.file_syntax(file_id);
        Some(SourceChange::from_local_edit(
            file_id,
            "add semicolon",
            ra_editor::on_eq_typed(&file, offset)?,
        ))
    }
    pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
        let file = self.imp.file_syntax(file_id);
        ra_editor::file_structure(&file)
    }
    pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
        let file = self.imp.file_syntax(file_id);
        ra_editor::folding_ranges(&file)
    }
    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.world_symbols(query)
    }
    pub fn approximately_resolve_symbol(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.approximately_resolve_symbol(file_id, offset)
    }
    pub fn find_all_refs(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Vec<(FileId, TextRange)>> {
        Ok(self.imp.find_all_refs(file_id, offset))
    }
    pub fn parent_module(&self, file_id: FileId) -> Cancelable<Vec<(FileId, FileSymbol)>> {
        self.imp.parent_module(file_id)
    }
    pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
        self.imp.crate_for(file_id)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
        Ok(self.imp.crate_root(crate_id))
    }
    pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
        let file = self.imp.file_syntax(file_id);
        Ok(ra_editor::runnables(&file))
    }
    pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
        let file = self.imp.file_syntax(file_id);
        Ok(ra_editor::highlight(&file))
    }
    pub fn completions(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Option<Vec<CompletionItem>>> {
        self.imp.completions(file_id, offset)
    }
    pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable<Vec<SourceChange>> {
        Ok(self.imp.assists(file_id, range))
    }
    pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
        self.imp.diagnostics(file_id)
    }
    pub fn resolve_callable(
        &self,
        file_id: FileId,
        offset: TextUnit,
    ) -> Cancelable<Option<(FnDescriptor, Option<usize>)>> {
        self.imp.resolve_callable(file_id, offset)
    }
}

#[derive(Debug)]
pub struct LibraryData {
    files: Vec<(FileId, String)>,
    file_resolver: FileResolverImp,
    symbol_index: SymbolIndex,
}

impl LibraryData {
    pub fn prepare(files: Vec<(FileId, String)>, file_resolver: Arc<FileResolver>) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, text)| {
            let file = File::parse(text);
            (*file_id, file)
        }));
        LibraryData {
            files,
            file_resolver: FileResolverImp::new(file_resolver),
            symbol_index,
        }
    }
}

#[test]
fn analysis_is_send() {
    fn is_send<T: Send>() {}
    is_send::<Analysis>();
}
<|endoftext|>


<commit_before>extern mod std;
extern mod extra;

struct ChildNode {
    r: int;
    g: int;
    b: int;
    x: int;
    y: int;

}

impl ChildNode {

}

struct ParentNode {
    // will need a port,chan here
}
<commit_msg>updated for pixels.<commit_after>extern mod std;
extern mod extra;

struct ChildNode {
    x: int;
    y: int;

}

impl ChildNode {

}

struct ParentNode {
    // will need a port,chan here
}

struct Pixel {
    r: int;
    g: int;
    b: int;
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use std::process::exit;
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{echo} */ r#"
NAME
    echo - display a line of text

SYNOPSIS
    echo [ -h | --help ] [-e] [-n] [-s] [STRING]...

DESCRIPTION
    Print the STRING(s) to standard output.

OPTIONS
    -e
        enable the interpretation of backslash escapes
    -n
        do not output the trailing newline
    -s
        do not separate arguments with spaces

    Escape Sequences
        When the -e argument is used, the following sequences will be interpreted:

        \\  backslash
        \a  alert (BEL)
        \b  backspace (BS)
        \c  produce no further output
        \e  escape (ESC)
        \f  form feed (FF)
        \n  new line
        \r  carriage return
        \t  horizontal tab (HT)
        \v  vertical tab (VT)

"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(4)
        .add_flag("e", "escape")
        .add_flag("n", "no-newline")
        .add_flag("s", "no-spaces")
        .add_flag("h", "help");
    parser.parse(env::args());

    if parser.found(&'h') || parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    // Print to standard output
    let mut first = true;
    for arg in parser.args.iter().map(|x| x.as_bytes()) {
        if first {
            first = false;
        } else if !(parser.found(&'s') || parser.found("no-spaces")) {
            stdout.write(&[b' ']).try(&mut stderr);
        }
        if parser.found(&'e') || parser.found("escape") {
            let mut check = false;
            for &byte in arg {
                match byte {
                    b'\\' if check => {
                        stdout.write(&[byte]).try(&mut stderr);
                        check = false;
                    },
                    b'\\' => check = true,
                    b'a' if check => {
                        stdout.write(&[7u8]).try(&mut stderr); // bell
                        check = false;
                    },
                    b'b' if check => {
                        stdout.write(&[8u8]).try(&mut stderr); // backspace
                        check = false;
                    },
                    b'c' if check => {
                        exit(0);
                    },
                    b'e' if check => {
                        stdout.write(&[27u8]).try(&mut stderr); // escape
                        check = false;
                    },
                    b'f' if check => {
                        stdout.write(&[12u8]).try(&mut stderr); // form feed
                        check = false;
                    },
                    b'n' if check => {
                        stdout.write(&[b'\n']).try(&mut stderr); // newline
                        check = false;
                    },
                    b'r' if check => {
                        stdout.write(&[b'\r']).try(&mut stderr);
                        check = false;
                    },
                    b't' if check => {
                        stdout.write(&[b'\t']).try(&mut stderr);
                        check = false;
                    },
                    b'v' if check => {
                        stdout.write(&[11u8]).try(&mut stderr); // vertical tab
                        check = false;
                    },
                    _ if check => {
                        stdout.write(&[b'\\', byte]).try(&mut stderr);
                        check = false;
                    },
                    _ => { stdout.write(&[byte]).try(&mut stderr); }
                }
            }
        } else {
            stdout.write(arg).try(&mut stderr);
        }
    }

    if !(parser.found(&'n') || parser.found("no-newline")) {
        stdout.write(&[b'\n']).try(&mut stderr);
    }
}
<commit_msg>echo adheres to new ArgParser interface<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use std::process::exit;
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{echo} */ r#"
NAME
    echo - display a line of text

SYNOPSIS
    echo [ -h | --help ] [-e] [-n] [-s] [STRING]...

DESCRIPTION
    Print the STRING(s) to standard output.

OPTIONS
    -e
        enable the interpretation of backslash escapes
    -n
        do not output the trailing newline
    -s
        do not separate arguments with spaces

    Escape Sequences
        When the -e argument is used, the following sequences will be interpreted:

        \\  backslash
        \a  alert (BEL)
        \b  backspace (BS)
        \c  produce no further output
        \e  escape (ESC)
        \f  form feed (FF)
        \n  new line
        \r  carriage return
        \t  horizontal tab (HT)
        \v  vertical tab (VT)

"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(4)
        .add_flag(&["e", "escape"])
        .add_flag(&["n", "no-newline"])
        .add_flag(&["s", "no-spaces"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    // Print to standard output
    let mut first = true;
    for arg in parser.args.iter().map(|x| x.as_bytes()) {
        if first {
            first = false;
        } else if ! parser.found("no-spaces") {
            stdout.write(&[b' ']).try(&mut stderr);
        }
        if parser.found("escape") {
            let mut check = false;
            for &byte in arg {
                match byte {
                    b'\\' if check => {
                        stdout.write(&[byte]).try(&mut stderr);
                        check = false;
                    },
                    b'\\' => check = true,
                    b'a' if check => {
                        stdout.write(&[7u8]).try(&mut stderr); // bell
                        check = false;
                    },
                    b'b' if check => {
                        stdout.write(&[8u8]).try(&mut stderr); // backspace
                        check = false;
                    },
                    b'c' if check => {
                        exit(0);
                    },
                    b'e' if check => {
                        stdout.write(&[27u8]).try(&mut stderr); // escape
                        check = false;
                    },
                    b'f' if check => {
                        stdout.write(&[12u8]).try(&mut stderr); // form feed
                        check = false;
                    },
                    b'n' if check => {
                        stdout.write(&[b'\n']).try(&mut stderr); // newline
                        check = false;
                    },
                    b'r' if check => {
                        stdout.write(&[b'\r']).try(&mut stderr);
                        check = false;
                    },
                    b't' if check => {
                        stdout.write(&[b'\t']).try(&mut stderr);
                        check = false;
                    },
                    b'v' if check => {
                        stdout.write(&[11u8]).try(&mut stderr); // vertical tab
                        check = false;
                    },
                    _ if check => {
                        stdout.write(&[b'\\', byte]).try(&mut stderr);
                        check = false;
                    },
                    _ => { stdout.write(&[byte]).try(&mut stderr); }
                }
            }
        } else {
            stdout.write(arg).try(&mut stderr);
        }
    }

    if ! parser.found("no-newline") {
        stdout.write(&[b'\n']).try(&mut stderr);
    }
}
<|endoftext|>


<commit_before>// we need to compile and link to our library crate
// by default the `name = ???` of the [lib] is the same as the package name, so we extern crate to `mazes`

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate mazes;

use mazes::squaregrid::SquareGrid;
use mazes::generators;

fn main() {
    let mut sg = SquareGrid::<u16>::new(20);
    generators::binary_tree(&mut sg);
    println!("{}", sg);

    println!("");
    println!("");
    println!("");

    let mut sg_2 = SquareGrid::<u16>::new(50);
    generators::sidewinder(&mut sg_2);
    println!("{}", sg_2);
}
<commit_msg>Grid size as command line argument.<commit_after>// we need to compile and link to our library crate
// by default the `name = ???` of the [lib] is the same as the package name, so we extern crate to `mazes`

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

extern crate mazes;

use std::env;

use mazes::squaregrid::SquareGrid;
use mazes::generators;

fn main() {

    let grid_size = env::args().nth(1).map_or(20, |n_str| {
        n_str.parse::<u16>()
             .ok()
             .expect("Command Line Arg[1] (the grid size) should be a positive number")
    });

    let mut sg = SquareGrid::<u16>::new(grid_size);
    generators::binary_tree(&mut sg);
    println!("{}", sg);

    println!("");
    println!("");
    println!("");

    let mut sg_2 = SquareGrid::<u16>::new(grid_size);
    generators::sidewinder(&mut sg_2);
    println!("{}", sg_2);
}
<|endoftext|>