<commit_before>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::PartialEq;
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

const SIGN_MASK: u32 = 0b1_00000_000000_00000000000000000000;
const COMBINATION_MASK: u32 = 0b0_11111_000000_00000000000000000000;

/// Represents a 32-bit decimal number according to the IEEE 754-2008 standard.
///
/// Decimal32 supports 7 decimal digits of significand and an exponent range of −95 to +96, i.e.
/// ±0.000000×10^−95 to ±9.999999×10^96. (Equivalently, ±0000000×10^−101 to ±9999999×10^90.)
///
/// Read more [here](https://en.wikipedia.org/wiki/Decimal32_floating-point_format).
#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }

    /// Creates and initializes a Decimal32 representation of positive infinity.
    pub fn infinity() -> Decimal32 {
        Decimal32 {
            data: 0b0_11110_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 representation of negative infinity.
    pub fn neg_infinity() -> Decimal32 {
        Decimal32 {
            data: 0b1_11110_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a quiet NaN.
    pub fn quiet_nan() -> Decimal32 {
        Decimal32 {
            data: 0b0_11111_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a signaling NaN.
    pub fn signaling_nan() -> Decimal32 {
        Decimal32 {
            data: 0b0_11111_100000_00000000000000000000
        }
    }

    /// Copies the data passed into the data in the Decimal32.
    pub fn from_data(data: u32) -> Decimal32 {
        Decimal32 { data: data }
    }

    /// Returns true if the combination field signifies infinity, and false otherwise.
    pub fn is_infinity(&self) -> bool {
        self.get_combination_field() == 0b11110
    }

    /// Returns true if the combination field signifies infinity and the sign is positive, and false
    /// otherwise.
    pub fn is_pos_infinity(&self) -> bool {
        self.is_positive() && self.is_infinity()
    }

    /// Returns true if the combination field signifies infinity and the sign is negative, and false
    /// otherwise.
    pub fn is_neg_infinity(&self) -> bool {
        self.is_negative() && self.is_infinity()
    }

    /// Returns true if the combination field signifies NaN, and false otherwise.
    pub fn is_nan(&self) -> bool {
        self.get_combination_field() == 0b11111
    }

    fn get_sign_field(&self) -> u32 {
        (self.data & SIGN_MASK) >> 31
    }

    fn get_combination_field(&self) -> u32 {
        (self.data & COMBINATION_MASK) >> 26
    }

    fn get_first_two_bits_combination_field(&self) -> u32 {
        let combination_field = self.get_combination_field();
        combination_field >> 3
    }

    fn get_second_two_bits_combination_field(&self) -> u32 {
        let mask = 0b00110;
        let combination_field = self.get_combination_field();
        (combination_field & mask) >> 1
    }

    fn get_normal_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00111_111000_00000000000000000000;
        (self.data & mask) >> 23
    }

    fn get_shifted_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00001_111110_00000000000000000000;
        (self.data & mask) >> 21
    }

    fn get_normal_significand(&self) -> u32 {
        let mask = 0b0_00000_000111_11111111111111111111;
        self.data & mask
    }

    fn get_shifted_significand(&self) -> u32 {
        let implicit_100 = 0b100_0_00000_00000_00000_00000;
        let mask = 0b0_00000_000001_11111111111111111111;
        implicit_100 + (self.data & mask)
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        let sum;
        let sign = self.get_sign_field();
        if self.is_nan() || other.is_nan() {
            sum = Decimal32::quiet_nan();
        } else if self.is_infinity() {
            if other.is_infinity() {
                sum = Decimal32::infinity();
            }
        } else {
            let exponent;
            let significand;
            if self.get_first_two_bits_combination_field() < 3 {
                exponent = self.get_normal_exponent();
                significand = self.get_normal_significand();
            } else { // self.get_second_two_bits_combination_field() < 3
                exponent = self.get_shifted_exponent();
                significand = self.get_shifted_significand();
            }
            // TODO sum =...
        }
        sum
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 { data: self.data ^ 1 << 31 }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000000 }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000001 }
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.get_sign_field() == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.get_sign_field() != 0
    }
}
    <commit_msg>able to build a decimal32 from data parts<commit_after>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::PartialEq;
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

const SIGN_MASK: u32 = 0b1_00000_000000_00000000000000000000;
const COMBINATION_MASK: u32 = 0b0_11111_000000_00000000000000000000;

/// Represents a 32-bit decimal number according to the IEEE 754-2008 standard.
///
/// Decimal32 supports 7 decimal digits of significand and an exponent range of −95 to +96, i.e.
/// ±0.000000×10^−95 to ±9.999999×10^96. (Equivalently, ±0000000×10^−101 to ±9999999×10^90.)
///
/// Read more [here](https://en.wikipedia.org/wiki/Decimal32_floating-point_format).
#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }

    /// Creates and initialize a Decimal32 from its significant parts: the sign, exponent, and
    /// significand, respectively.
    ///
    /// Returns Err(String) if either the exponent or significand is out of range.
    pub fn from_data(is_negative: bool,
                     exponent: i32,
                     significand: u32)
                     -> Result<Decimal32, String> {
        if exponent < -101 {
            Err("Exponent cannot be less than -101.".to_string())
        } else if exponent > 90 {
            Err("Exponent cannot be greater than 90.".to_string())
        } else if significand > 10_485_759 {
            Err("Significand cannot be greater than 10,485,759.".to_string())
        } else {
            let sign_field = (if is_negative { 1 } else { 0 }) << 31;
            let stored_exponent = ((exponent + 101) as u32);

            let implicit_field;
            let exponent_field;
            let significand_field;
            if significand < 8_388_608 {
                implicit_field = 0;
                exponent_field = stored_exponent << 23; // TODO think
                significand_field = significand;
            } else {
                // 8,388,608 is the first number that requires the implicit (100) in the significand
                implicit_field = 0b11 << 29;
                exponent_field = stored_exponent << 21;
                // remove the implicit (100)
                significand_field = significand - 0b1000_0000_0000_0000_0000_0000;
            }
            let ok_result = Decimal32 {
                data: sign_field + implicit_field + exponent_field + significand_field
            };
            Ok(ok_result)
        }
    }

    /// Creates and initializes a Decimal32 representation of positive infinity.
    pub fn infinity() -> Decimal32 {
        Decimal32 { data: 0b0_11110_000000_00000000000000000000 }
    }

    /// Creates and initializes a Decimal32 representation of negative infinity.
    pub fn neg_infinity() -> Decimal32 {
        Decimal32 { data: 0b1_11110_000000_00000000000000000000 }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a quiet NaN.
    pub fn quiet_nan() -> Decimal32 {
        Decimal32 { data: 0b0_11111_000000_00000000000000000000 }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a quiet NaN.
    pub fn qnan() -> Decimal32 {
        Decimal32 { data: 0b0_11111_000000_00000000000000000000 }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a signaling NaN.
    pub fn signaling_nan() -> Decimal32 {
        Decimal32 { data: 0b0_11111_100000_00000000000000000000 }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a signaling NaN.
    pub fn snan() -> Decimal32 {
        Decimal32 { data: 0b0_11111_100000_00000000000000000000 }
    }

    /// Copies the data passed into the data in the Decimal32.
    pub fn from_bin(data: u32) -> Decimal32 {
        Decimal32 { data: data }
    }

    /// Returns true if the combination field signifies infinity, and false otherwise.
    pub fn is_infinity(&self) -> bool {
        self.get_combination_field() == 0b11110
    }

    /// Returns true if the combination field signifies infinity and the sign is positive, and false
    /// otherwise.
    pub fn is_pos_infinity(&self) -> bool {
        self.is_positive() && self.is_infinity()
    }

    /// Returns true if the combination field signifies infinity and the sign is negative, and false
    /// otherwise.
    pub fn is_neg_infinity(&self) -> bool {
        self.is_negative() && self.is_infinity()
    }

    /// Returns true if the combination field signifies NaN, and false otherwise.
    pub fn is_nan(&self) -> bool {
        self.get_combination_field() == 0b11111
    }

    /// Returns the three defining pieces of the decimal - the sign (true if negative), the
    /// exponent, and the significand, respectively.
    ///
    /// Do not expect well-behaved results if this decimal is NaN or infinity.
    pub fn get_data(&self) -> (bool, i32, u32) {
        let sign = self.get_sign_field() != 0;
        let (exponent, significand) = if self.get_first_two_bits_combination_field() < 3 {
            ((self.get_normal_exponent() as i32) - 101, self.get_normal_significand())
        } else {
            // self.get_second_two_bits_combination_field() < 3
            ((self.get_shifted_exponent() as i32) - 101, self.get_shifted_significand())
        };
        (sign, exponent, significand)
    }

    pub fn get_exponent(&self) -> i32 {
        let exponent = if self.get_first_two_bits_combination_field() < 3 {
            self.get_normal_exponent()
        } else {
            // self.get_second_two_bits_combination_field() < 3
            self.get_shifted_exponent()
        };
        (exponent as i32) - 101
    }

    fn get_sign_field(&self) -> u32 {
        (self.data & SIGN_MASK) >> 31
    }

    fn get_combination_field(&self) -> u32 {
        (self.data & COMBINATION_MASK) >> 26
    }

    fn get_first_two_bits_combination_field(&self) -> u32 {
        let combination_field = self.get_combination_field();
        combination_field >> 3
    }

    fn get_second_two_bits_combination_field(&self) -> u32 {
        let mask = 0b00110;
        let combination_field = self.get_combination_field();
        (combination_field & mask) >> 1
    }

    fn get_normal_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00111_111000_00000000000000000000;
        (self.data & mask) >> 23
    }

    fn get_shifted_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00001_111110_00000000000000000000;
        (self.data & mask) >> 21
    }

    fn get_normal_significand(&self) -> u32 {
        let mask = 0b0_00000_000111_11111111111111111111;
        self.data & mask
    }

    fn get_shifted_significand(&self) -> u32 {
        let implicit_100 = 0b100_0_00000_00000_00000_00000;
        let mask = 0b0_00000_000001_11111111111111111111;
        implicit_100 + (self.data & mask)
    }

    fn shift_exponent(&self, factor: i32) -> Decimal32 {
        let (_, exponent, significand) = self.get_data();
        let shifted_exponent = exponent + factor;
        let shifted_significand = (significand as f64) * 10f64.powi(-factor);
        unimplemented!()
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        let sign = self.get_sign_field();

        if self.is_nan() || other.is_nan() {
            // if either operand is NaN, so is the result
            Decimal32::qnan()
        } else if self.is_infinity() {
            if self.is_positive() {
                if other.is_neg_infinity() {
                    // if the operands are opposing infinities, the result is sNaN
                    Decimal32::snan()
                } else {
                    // if the left operand is positive infinity, and the other is not negative
                    // infinity or NaN, the result is positive infinity
                    Decimal32::infinity()
                }
            } else {
                if other.is_pos_infinity() {
                    // if the operands are opposing infinities, the result is sNaN
                    Decimal32::snan()
                } else {
                    // if the left operand is negative infinity, and the other is not positive
                    // infinity or NaN, the result is negative infinity
                    Decimal32::neg_infinity()
                }
            }
        } else if other.is_infinity() {
            if other.is_positive() {
                if self.is_neg_infinity() {
                    // if the operands are opposing infinities, the result is sNaN
                    Decimal32::snan()
                } else {
                    // if the left operand is positive infinity, and the other is not negative
                    // infinity or NaN, the result is positive infinity
                    Decimal32::infinity()
                }
            } else {
                if self.is_pos_infinity() {
                    // if the operands are opposing infinities, the result is sNaN
                    Decimal32::snan()
                } else {
                    // if the left operand is negative infinity, and the other is not positive
                    // infinity or NaN, the result is negative infinity
                    Decimal32::neg_infinity()
                }
            }
        } else {
            let exponent;
            let significand;
            if self.get_first_two_bits_combination_field() < 3 {
                exponent = self.get_normal_exponent();
                significand = self.get_normal_significand();
            } else {
                // self.get_second_two_bits_combination_field() < 3
                exponent = self.get_shifted_exponent();
                significand = self.get_shifted_significand();
            }
            unimplemented!() // TODO
        }
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 { data: self.data ^ 1 << 31 }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000000 }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000001 }
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.get_sign_field() == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.get_sign_field() != 0
    }
}
    <|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::PartialEq;
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

const SIGN_MASK: u32 = 0b1_00000_000000_00000000000000000000;
const COMBINATION_MASK: u32 = 0b0_11111_000000_00000000000000000000;

#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }

    fn get_sign_field(&self) -> u32 {
        (self.data & SIGN_MASK) >> 31
    }

    fn get_combination_field(&self) -> u32 {
        (self.data & COMBINATION_MASK) >> 26
    }

    fn get_first_two_bits_combination_field(&self) -> u32 {
        let combination_field = self.get_combination_field();
        combination_field >> 3
    }

    fn get_second_two_bits_combination_field(&self) -> u32 {
        let mask = 0b00110;
        let combination_field = self.get_combination_field();
        (combination_field & mask) >> 1
    }

    fn get_normal_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00111_111000_00000000000000000000;
        (self.data & mask) >> 23
    }

    fn get_shifted_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00001_111110_00000000000000000000;
        (self.data & mask) >> 21
    }

    fn get_normal_significand(&self) -> u32 {
        let mask = 0b0_00000_000111_11111111111111111111;
        self.data & mask
    }

    fn get_shifted_significand(&self) -> u32 {
        let implicit_100 = 0b100_0_00000_00000_00000_00000;
        let mask = 0b0_00000_000001_11111111111111111111;
        implicit_100 + (self.data & mask)
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 { data: self.data ^ 1 << 31 }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000000 }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000001 }
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.get_sign_field() == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.get_sign_field() != 0
    }
}
    <commit_msg>add covers special cases, but not the general case<commit_after>use std::ops::{Add, Sub, Mul, Div, Neg, Rem};
use std::cmp::PartialEq;
use super::super::num::{Num, Zero, One, Signed};
use super::parse_decimal_error::ParseDecimalError;

const SIGN_MASK: u32 = 0b1_00000_000000_00000000000000000000;
const COMBINATION_MASK: u32 = 0b0_11111_000000_00000000000000000000;

#[derive(Debug, Clone, Copy)]
pub struct Decimal32 {
    data: u32,
}

impl Decimal32 {
    /// Creates and initializes a Decimal32 representation of zero.
    pub fn new() -> Decimal32 {
        Decimal32::zero()
    }

    /// Creates and initializes a Decimal32 representation of positive infinity.
    pub fn infinity() -> Decimal32 {
        Decimal32 {
            data: 0b0_11110_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 representation of negative infinity.
    pub fn neg_infinity() -> Decimal32 {
        Decimal32 {
            data: 0b1_11110_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a quiet NaN.
    pub fn quiet_nan() -> Decimal32 {
        Decimal32 {
            data: 0b0_11111_000000_00000000000000000000
        }
    }

    /// Creates and initializes a Decimal32 that is specially encoded as a signaling NaN.
    pub fn signaling_nan() -> Decimal32 {
        Decimal32 {
            data: 0b0_11111_100000_00000000000000000000
        }
    }

    /// Copies the data passed into the data in the Decimal32.
    pub fn from_data(data: u32) -> Decimal32 {
        Decimal32 { data: data }
    }

    /// Returns true if the combination field signifies infinity, and false otherwise.
    pub fn is_infinity(&self) -> bool {
        self.get_combination_field() == 0b11110
    }

    /// Returns true if the combination field signifies infinity and the sign is positive, and false
    /// otherwise.
    pub fn is_pos_infinity(&self) -> bool {
        self.is_positive() && self.is_infinity()
    }

    /// Returns true if the combination field signifies infinity and the sign is negative, and false
    /// otherwise.
    pub fn is_neg_infinity(&self) -> bool {
        self.is_negative() && self.is_infinity()
    }

    /// Returns true if the combination field signifies NaN, and false otherwise.
    pub fn is_nan(&self) -> bool {
        self.get_combination_field() == 0b11111
    }

    fn get_sign_field(&self) -> u32 {
        (self.data & SIGN_MASK) >> 31
    }

    fn get_combination_field(&self) -> u32 {
        (self.data & COMBINATION_MASK) >> 26
    }

    fn get_first_two_bits_combination_field(&self) -> u32 {
        let combination_field = self.get_combination_field();
        combination_field >> 3
    }

    fn get_second_two_bits_combination_field(&self) -> u32 {
        let mask = 0b00110;
        let combination_field = self.get_combination_field();
        (combination_field & mask) >> 1
    }

    fn get_normal_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00111_111000_00000000000000000000;
        (self.data & mask) >> 23
    }

    fn get_shifted_exponent(&self) -> u32 {
        let mask: u32 = 0b0_00001_111110_00000000000000000000;
        (self.data & mask) >> 21
    }

    fn get_normal_significand(&self) -> u32 {
        let mask = 0b0_00000_000111_11111111111111111111;
        self.data & mask
    }

    fn get_shifted_significand(&self) -> u32 {
        let implicit_100 = 0b100_0_00000_00000_00000_00000;
        let mask = 0b0_00000_000001_11111111111111111111;
        implicit_100 + (self.data & mask)
    }
}

impl Add<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn add(self, other: Decimal32) -> Decimal32 {
        let sum;
        let sign = self.get_sign_field();
        if self.is_nan() || other.is_nan() {
            sum = Decimal32::quiet_nan();
        } else if self.is_infinity() {
            if other.is_infinity() {
                sum = Decimal32::infinity();
            }
        } else {
            let exponent;
            let significand;
            if self.get_first_two_bits_combination_field() < 3 {
                exponent = self.get_normal_exponent();
                significand = self.get_normal_significand();
            } else { // self.get_second_two_bits_combination_field() < 3
                exponent = self.get_shifted_exponent();
                significand = self.get_shifted_significand();
            }
            // TODO sum =...
        }
        sum
    }
}

impl Sub<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn sub(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Mul<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn mul(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Div<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn div(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl Neg for Decimal32 {
    type Output = Decimal32;

    fn neg(self) -> Decimal32 {
        Decimal32 { data: self.data ^ 1 << 31 }
    }
}

impl Rem<Decimal32> for Decimal32 {
    type Output = Decimal32;

    fn rem(self, other: Decimal32) -> Decimal32 {
        self // TODO
    }
}

impl PartialEq for Decimal32 {
    fn eq(&self, other: &Decimal32) -> bool {
        true // TODO
    }
}

impl Num for Decimal32 {
    type FromStrRadixErr = ParseDecimalError;

    fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Decimal32::zero()) // TODO
    }
}

impl Zero for Decimal32 {
    fn zero() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000000 }
    }

    fn is_zero(&self) -> bool {
        true
    }
}

impl One for Decimal32 {
    fn one() -> Decimal32 {
        Decimal32 { data: 0b0_00000_000000_00000000000000000001 }
    }
}

impl Signed for Decimal32 {
    fn abs(&self) -> Decimal32 {
        Decimal32 { data: self.data & (!SIGN_MASK) }
    }

    fn abs_sub(&self, other: &Decimal32) -> Decimal32 {
        // TODO
        // The positive difference of two numbers.
        // Returns zero if the number is less than or equal to other, otherwise the difference between self and other is returned.
        *self
    }

    fn signum(&self) -> Decimal32 {
        // TODO
        // Returns the sign of the number.
        // For f32 and f64:
        // 1.0 if the number is positive, +0.0 or INFINITY
        // -1.0 if the number is negative, -0.0 or NEG_INFINITY
        // NaN if the number is NaN
        *self
    }

    /// Note: Zero can be positive or negative.
    fn is_positive(&self) -> bool {
        self.get_sign_field() == 0
    }

    /// Note: Zero can be positive or negative.
    fn is_negative(&self) -> bool {
        self.get_sign_field() != 0
    }
}
    <|endoftext|>


<commit_before>//! It's a tree!

use std::ptr;
use std::ops::{Deref, DerefMut};
use std::fmt::Debug;

#[derive(Debug, PartialEq, Eq)]
struct Node<T> {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node<T>,
    val: T,
    children: Vec<Node<T>>
}

impl<T> Node<T> {
    /// Create a new node with the existing value.
    /// For root-style constructors.
    pub fn new(val: T) -> Node<T> {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    /// Add a new child node to this node, using a value
    pub fn new_child(&mut self, val: T) {
        let self_mut = self as *mut Node<T>;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        })
    }

    /// Whether this node has a (currently-reachable) parent
    pub fn has_parent(&self) -> bool {
        self.parent.is_null()
    }

    /// Gets the parent of this node (if it exists)
    pub fn get_parent<'a>(&'a self) -> Option<&'a mut Node<T>> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Borrow the children of this node.
    pub fn get_children<'a>(&'a self) -> &Vec<Node<T>> {
        &self.children
    }

    /// Mutably borrow the children of this mutable node
    pub fn get_mut_children(&mut self) -> &mut Vec<Node<T>> {
        &mut self.children
    }

    /// Remove a child at the given index
    pub fn remove_child_at(&mut self, index: usize) -> Node<T> {
        self.children.remove(index)
    }

    /// Whether this node is a parent of another node
    pub fn is_parent_of(&self, other: Node<T>) -> bool {
        self.parent == other.parent
    }
}

impl <T: PartialEq> Node<T> {
    pub fn remove_from_parent(&self) {
        if let Some(ref mut parent) = self.get_parent() {
            let children = parent.get_mut_children();
            if let Some(index) = children.iter().position(|c| c == self) {
                children.remove(index);
            }
        }
    }

    pub fn remove_child(&mut self, other: &Node<T>) -> Option<Node<T>> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            Some(self.children.remove(index))
        }
        else {
            None
        }
    }

    pub fn move_to(mut self, new_parent: &mut Node<T>) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node<T>;
        new_parent.children.push(self);
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        trace!("Dropping a node!!!!");
        self.parent = ptr::null_mut();
    }
}

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

    fn test_add_child() {

    }
}
<commit_msg>Update unsafetree.rs<commit_after>//! It's a tree!

use std::ptr;
use std::ops::{Deref, DerefMut};
use std::fmt::Debug;

#[derive(Debug, PartialEq, Eq)]
struct Node<T> {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node<T>,
    val: T,
    children: Vec<Node<T>>
}

impl<T> Node<T> {
    /// Create a new node with the existing value.
    /// For root-style constructors.
    pub fn new(val: T) -> Node<T> {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    /// Add a new child node to this node, using a value
    pub fn new_child(&mut self, val: T) {
        let self_mut = self as *mut Node<T>;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        })
    }

    /// Whether this node has a (currently-reachable) parent
    pub fn has_parent(&self) -> bool {
        self.parent.is_null()
    }

    /// Gets the parent of this node (if it exists)
    pub fn get_parent<'a>(&'a self) -> Option<&'a mut Node<T>> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Borrow the children of this node.
    pub fn get_children<'a>(&'a self) -> &Vec<Node<T>> {
        &self.children
    }

    /// Mutably borrow the children of this mutable node
    pub fn get_mut_children(&mut self) -> &mut Vec<Node<T>> {
        &mut self.children
    }

    /// Remove a child at the given index
    pub fn remove_child_at(&mut self, index: usize) -> Node<T> {
        let child = self.children.remove(index);
        child.parent = ptr::null_mut();
        child
    }

    /// Whether this node is a parent of another node
    pub fn is_parent_of(&self, other: Node<T>) -> bool {
        self.parent == other.parent
    }
}

impl <T: PartialEq> Node<T> {
    pub fn remove_from_parent(&self) {
        if let Some(ref mut parent) = self.get_parent() {
            let children = parent.get_mut_children();
            if let Some(index) = children.iter().position(|c| c == self) {
                children.remove(index);
            }
        }
    }

    pub fn remove_child(&mut self, other: &Node<T>) -> Option<Node<T>> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            Some(self.children.remove(index))
        }
        else {
            None
        }
    }

    pub fn move_to(mut self, new_parent: &mut Node<T>) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node<T>;
        new_parent.children.push(self);
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        trace!("Dropping a node!!!!");
    }
}

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

    fn test_add_child() {

    }
}
<|endoftext|>


<commit_before>use crate::evaluation::environment;
use crate::token;

type ObjectType = String;

pub trait ObjectT {
    fn object_type(&self) -> ObjectType;
    fn inspect(&self) -> String;
}

// **********************************************
// * Interpreted object represanted as sum type *
// **********************************************
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Object {
    Integer(Integer),
    Boolean(Boolean),
    Nil(Nil),
    ReturnValue(Box<ReturnValue>),
    Error(Error),
}

impl ObjectT for Object {
    fn object_type(&self) -> ObjectType {
        match self {
            Object::Integer(i) => i.object_type(),
            Object::Boolean(b) => b.object_type(),
            Object::Nil(n) => n.object_type(),
            Object::ReturnValue(rv) => rv.object_type(),
            Object::Error(err) => err.object_type(),
        }
    }

    fn inspect(&self) -> String {
        match self {
            Object::Integer(i) => i.inspect(),
            Object::Boolean(b) => b.inspect(),
            Object::Nil(n) => n.inspect(),
            Object::ReturnValue(rv) => rv.inspect(),
            Object::Error(err) => err.inspect(),
        }
    }
}

// ************************************************
// * Internal represantion of interpreted objects.*
// ************************************************

// Integer value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Integer {
    pub value: i32,
}

impl ObjectT for Integer {
    fn object_type(&self) -> ObjectType {
        "INTEGER".to_string()
    }

    fn inspect(&self) -> String {
        self.value.to_string()
    }
}

// Boolean value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Boolean {
    pub value: bool,
}

impl ObjectT for Boolean {
    fn object_type(&self) -> ObjectType {
        "BOOLEAN".to_string()
    }

    fn inspect(&self) -> String {
        self.value.to_string()
    }
}

// Nil value (billion dollar mistake should be in every language, lol)
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Nil {}

impl ObjectT for Nil {
    fn object_type(&self) -> ObjectType {
        "NULL".to_string()
    }

    fn inspect(&self) -> String {
        "null".to_string()
    }
}

// ReturnValue
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReturnValue {
    pub value: Object,
}

impl ObjectT for ReturnValue {
    fn object_type(&self) -> ObjectType {
        "RETURN_VALUE".to_string()
    }

    fn inspect(&self) -> String {
        self.value.inspect()
    }
}

// Error value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Error {
    pub message: String,
}

impl ObjectT for Error {
    fn object_type(&self) -> ObjectType {
        "ERROR".to_string()
    }

    fn inspect(&self) -> String {
        self.message.to_string()
    }
}

// Function object
#[derive(Debug, Clone)]
pub struct Function {
    pub parameters: Option<Vec<token::Identifier>>,
    pub body: token::BlockStatement,
    pub env: environment::Environment,
}

impl ObjectT for Function {
    fn object_type(&self) -> ObjectType {
        "FUNCTION".to_string()
    }

    fn inspect(&self) -> String {
        let params = match self.parameters.clone() {
            Some(params) => params
                .iter()
                .map(ToString::to_string)
                .collect::<Vec<_>>()
                .join(","),
            None => "".to_string(),
        };

        format!("fn({}){{{}}}", params, self.body)
    }
}
<commit_msg>minor styling for function inspection<commit_after>use crate::evaluation::environment;
use crate::token;

type ObjectType = String;

pub trait ObjectT {
    fn object_type(&self) -> ObjectType;
    fn inspect(&self) -> String;
}

// **********************************************
// * Interpreted object represanted as sum type *
// **********************************************
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Object {
    Integer(Integer),
    Boolean(Boolean),
    Nil(Nil),
    ReturnValue(Box<ReturnValue>),
    Error(Error),
}

impl ObjectT for Object {
    fn object_type(&self) -> ObjectType {
        match self {
            Object::Integer(i) => i.object_type(),
            Object::Boolean(b) => b.object_type(),
            Object::Nil(n) => n.object_type(),
            Object::ReturnValue(rv) => rv.object_type(),
            Object::Error(err) => err.object_type(),
        }
    }

    fn inspect(&self) -> String {
        match self {
            Object::Integer(i) => i.inspect(),
            Object::Boolean(b) => b.inspect(),
            Object::Nil(n) => n.inspect(),
            Object::ReturnValue(rv) => rv.inspect(),
            Object::Error(err) => err.inspect(),
        }
    }
}

// ************************************************
// * Internal represantion of interpreted objects.*
// ************************************************

// Integer value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Integer {
    pub value: i32,
}

impl ObjectT for Integer {
    fn object_type(&self) -> ObjectType {
        "INTEGER".to_string()
    }

    fn inspect(&self) -> String {
        self.value.to_string()
    }
}

// Boolean value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Boolean {
    pub value: bool,
}

impl ObjectT for Boolean {
    fn object_type(&self) -> ObjectType {
        "BOOLEAN".to_string()
    }

    fn inspect(&self) -> String {
        self.value.to_string()
    }
}

// Nil value (billion dollar mistake should be in every language, lol)
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Nil {}

impl ObjectT for Nil {
    fn object_type(&self) -> ObjectType {
        "NULL".to_string()
    }

    fn inspect(&self) -> String {
        "null".to_string()
    }
}

// ReturnValue
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReturnValue {
    pub value: Object,
}

impl ObjectT for ReturnValue {
    fn object_type(&self) -> ObjectType {
        "RETURN_VALUE".to_string()
    }

    fn inspect(&self) -> String {
        self.value.inspect()
    }
}

// Error value
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Error {
    pub message: String,
}

impl ObjectT for Error {
    fn object_type(&self) -> ObjectType {
        "ERROR".to_string()
    }

    fn inspect(&self) -> String {
        self.message.to_string()
    }
}

// Function object
#[derive(Debug, Clone)]
pub struct Function {
    pub parameters: Option<Vec<token::Identifier>>,
    pub body: token::BlockStatement,
    pub env: environment::Environment,
}

impl ObjectT for Function {
    fn object_type(&self) -> ObjectType {
        "FUNCTION".to_string()
    }

    fn inspect(&self) -> String {
        let params = match self.parameters.clone() {
            Some(params) => params
                .iter()
                .map(ToString::to_string)
                .collect::<Vec<_>>()
                .join(","),
            None => "".to_string(),
        };

        format!("fn({}) {{{}}}", params, self.body)
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use either::*;
use libc;
use str::StrSlice;

pub trait Logger {
    fn log(&mut self, msg: Either<~str, &'static str>);
}

pub struct StdErrLogger;

impl Logger for StdErrLogger {
    fn log(&mut self, msg: Either<~str, &'static str>) {
        use io::{Writer, WriterUtil};

        if !should_log_console() {
            return;
        }

        let s: &str = match msg {
            Left(ref s) => {
                let s: &str = *s;
                s
            }
            Right(ref s) => {
                let s: &str = *s;
                s
            }
        };

        // Truncate the string
        let buf_bytes = 256;
        if s.len() > buf_bytes {
            let s = s.slice(0, buf_bytes) + "[...]";
            print(s);
        } else {
            print(s)
        };

        fn print(s: &str) {
            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
            dbg.write_str(s);
            dbg.write_str("\n");
            dbg.flush();
        }
    }
}

/// Configure logging by traversing the crate map and setting the
/// per-module global logging flags based on the logging spec
#[fixed_stack_segment] #[inline(never)]
pub fn init(crate_map: *u8) {
    use c_str::ToCStr;
    use os;
    use ptr;
    use option::{Some, None};

    let log_spec = os::getenv("RUST_LOG");
    match log_spec {
        Some(spec) => {
            do spec.with_c_str |buf| {
                unsafe { rust_update_log_settings(crate_map, buf) }
            }
        }
        None => {
            unsafe {
                rust_update_log_settings(crate_map, ptr::null());
            }
        }
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn console_on() { unsafe { rust_log_console_on() } }

#[fixed_stack_segment] #[inline(never)]
pub fn console_off() { unsafe { rust_log_console_off() } }

#[fixed_stack_segment] #[inline(never)]
fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } }

extern {
    fn rust_update_log_settings(crate_map: *u8, settings: *libc::c_char);
    fn rust_log_console_on();
    fn rust_log_console_off();
    fn rust_should_log_console() -> libc::uintptr_t;
}

<commit_msg>Rangechange the log message truncation limit.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use either::*;
use libc;
use str::StrSlice;

pub trait Logger {
    fn log(&mut self, msg: Either<~str, &'static str>);
}

pub struct StdErrLogger;

impl Logger for StdErrLogger {
    fn log(&mut self, msg: Either<~str, &'static str>) {
        use io::{Writer, WriterUtil};

        if !should_log_console() {
            return;
        }

        let s: &str = match msg {
            Left(ref s) => {
                let s: &str = *s;
                s
            }
            Right(ref s) => {
                let s: &str = *s;
                s
            }
        };

        // Truncate the string
        let buf_bytes = 2048;
        if s.len() > buf_bytes {
            let s = s.slice(0, buf_bytes) + "[...]";
            print(s);
        } else {
            print(s)
        };

        fn print(s: &str) {
            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
            dbg.write_str(s);
            dbg.write_str("\n");
            dbg.flush();
        }
    }
}

/// Configure logging by traversing the crate map and setting the
/// per-module global logging flags based on the logging spec
#[fixed_stack_segment] #[inline(never)]
pub fn init(crate_map: *u8) {
    use c_str::ToCStr;
    use os;
    use ptr;
    use option::{Some, None};

    let log_spec = os::getenv("RUST_LOG");
    match log_spec {
        Some(spec) => {
            do spec.with_c_str |buf| {
                unsafe { rust_update_log_settings(crate_map, buf) }
            }
        }
        None => {
            unsafe {
                rust_update_log_settings(crate_map, ptr::null());
            }
        }
    }
}

#[fixed_stack_segment] #[inline(never)]
pub fn console_on() { unsafe { rust_log_console_on() } }

#[fixed_stack_segment] #[inline(never)]
pub fn console_off() { unsafe { rust_log_console_off() } }

#[fixed_stack_segment] #[inline(never)]
fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } }

extern {
    fn rust_update_log_settings(crate_map: *u8, settings: *libc::c_char);
    fn rust_log_console_on();
    fn rust_log_console_off();
    fn rust_should_log_console() -> libc::uintptr_t;
}

<|endoftext|>


<commit_before>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: BytePos,
    hi: BytePos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

// XXX col shouldn't be CharPos because col is not an absolute location in the
// codemap, and BytePos and CharPos always represent absolute positions
pub struct Loc {
    file: @FileMap, line: uint, col: CharPos
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

/// Identifies an offset of a multi-byte character in a FileMap
pub struct MultiByteChar {
    /// The absolute offset of the character in the CodeMap
    pos: BytePos,
    /// The number of bytes, >=2
    bytes: uint,
    /// The complete number of 'extra' bytes through this character in the
    /// FileMap
    sum: uint
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: BytePos,
    mut lines: ~[BytePos],
    multibyte_chars: DVec<MultiByteChar>
}

pub impl FileMap {
    fn next_line(&self, +pos: BytePos) {
        self.lines.push(pos);
    }

    pub fn get_line(&self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line] - self.start_pos;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

    pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {
        assert bytes >=2 && bytes <= 4;
        let sum = if self.multibyte_chars.len() > 0 {
            self.multibyte_chars.last().sum
        } else {
            0
        };
        let sum = sum + bytes;
        let mbc = MultiByteChar {
            pos: pos,
            bytes: bytes,
            sum: sum
        };
        self.multibyte_chars.push(mbc);
    }
}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    fn new_filemap_w_substr(+filename: FileName, +substr: FileSubstr,
                            src: @~str) -> @FileMap {
        let start_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };

        let filemap = @FileMap {
            name: filename, substr: substr, src: src,
            start_pos: BytePos(start_pos),
            mut lines: ~[],
            multibyte_chars: DVec()
        };

        self.files.push(filemap);

        return filemap;
    }

    fn new_filemap(+filename: FileName, src: @~str) -> @FileMap {
        return self.new_filemap_w_substr(filename, FssNone, src);
    }

    pub fn mk_substr_filename(&self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(&self, +pos: BytePos) -> Loc {
        return self.lookup_pos(pos);
    }

    pub fn lookup_char_pos_adj(&self, +pos: BytePos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(&self, sp: span) -> span {
        let line = self.lookup_line(sp.lo);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos),
                    hi: s.lo + (sp.hi - line.fm.start_pos),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(&self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(&self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    pub fn span_to_snippet(&self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(&self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {

    fn lookup_filemap_idx(&self, +pos: BytePos) -> uint {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if self.files[m].start_pos > pos {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }

        return a;
    }

    fn lookup_line(&self, +pos: BytePos)
        -> {fm: @FileMap, line: uint}
    {
        let idx = self.lookup_filemap_idx(pos);
        let f = self.files[idx];
        let mut a = 0u;
        let mut b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if f.lines[m] > pos { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos(&self, +pos: BytePos) -> Loc {
        let {fm: f, line: a} = self.lookup_line(pos);
        let line = a + 1u; // Line numbers start at 1
        let chpos = self.bytepos_to_local_charpos(pos);
        let linebpos = f.lines[a];
        let linechpos = self.bytepos_to_local_charpos(linebpos);
        debug!("codemap: byte pos %? is on the line at byte pos %?",
               pos, linebpos);
        debug!("codemap: char pos %? is on the line at char pos %?",
               chpos, linechpos);
        debug!("codemap: byte is on line: %?", line);
        assert chpos >= linechpos;
        return Loc {
            file: f,
            line: line,
            col: chpos - linechpos
        };
    }

    fn span_to_str_no_adj(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    fn lookup_byte_offset(&self, +bpos: BytePos)
        -> {fm: @FileMap, pos: BytePos} {
        let idx = self.lookup_filemap_idx(bpos);
        let fm = self.files[idx];
        let offset = bpos - fm.start_pos;
        return {fm: fm, pos: offset};
    }

    // Converts an absolute BytePos to a CharPos relative to the file it is
    // located in
    fn bytepos_to_local_charpos(&self, +bpos: BytePos) -> CharPos {
        debug!("codemap: converting %? to char pos", bpos);
        let idx = self.lookup_filemap_idx(bpos);
        let map = self.files[idx];

        // The number of extra bytes due to multibyte chars in the FileMap
        let mut total_extra_bytes = 0;

        for map.multibyte_chars.each |mbc| {
            debug!("codemap: %?-byte char at %?", mbc.bytes, mbc.pos);
            if mbc.pos < bpos {
                total_extra_bytes += mbc.bytes;
                // We should never see a byte position in the middle of a
                // character
                assert bpos == mbc.pos
                    || bpos.to_uint() >= mbc.pos.to_uint() + mbc.bytes;
            } else {
                break;
            }
        }

        CharPos(bpos.to_uint() - total_extra_bytes)
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>Remove incorrect comment from codemap<commit_after>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: BytePos,
    hi: BytePos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

pub struct Loc {
    file: @FileMap, line: uint, col: CharPos
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

/// Identifies an offset of a multi-byte character in a FileMap
pub struct MultiByteChar {
    /// The absolute offset of the character in the CodeMap
    pos: BytePos,
    /// The number of bytes, >=2
    bytes: uint,
    /// The complete number of 'extra' bytes through this character in the
    /// FileMap
    sum: uint
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: BytePos,
    mut lines: ~[BytePos],
    multibyte_chars: DVec<MultiByteChar>
}

pub impl FileMap {
    fn next_line(&self, +pos: BytePos) {
        self.lines.push(pos);
    }

    pub fn get_line(&self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line] - self.start_pos;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

    pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {
        assert bytes >=2 && bytes <= 4;
        let sum = if self.multibyte_chars.len() > 0 {
            self.multibyte_chars.last().sum
        } else {
            0
        };
        let sum = sum + bytes;
        let mbc = MultiByteChar {
            pos: pos,
            bytes: bytes,
            sum: sum
        };
        self.multibyte_chars.push(mbc);
    }
}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    fn new_filemap_w_substr(+filename: FileName, +substr: FileSubstr,
                            src: @~str) -> @FileMap {
        let start_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };

        let filemap = @FileMap {
            name: filename, substr: substr, src: src,
            start_pos: BytePos(start_pos),
            mut lines: ~[],
            multibyte_chars: DVec()
        };

        self.files.push(filemap);

        return filemap;
    }

    fn new_filemap(+filename: FileName, src: @~str) -> @FileMap {
        return self.new_filemap_w_substr(filename, FssNone, src);
    }

    pub fn mk_substr_filename(&self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(&self, +pos: BytePos) -> Loc {
        return self.lookup_pos(pos);
    }

    pub fn lookup_char_pos_adj(&self, +pos: BytePos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(&self, sp: span) -> span {
        let line = self.lookup_line(sp.lo);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos),
                    hi: s.lo + (sp.hi - line.fm.start_pos),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(&self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(&self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    pub fn span_to_snippet(&self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(&self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {

    fn lookup_filemap_idx(&self, +pos: BytePos) -> uint {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if self.files[m].start_pos > pos {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }

        return a;
    }

    fn lookup_line(&self, +pos: BytePos)
        -> {fm: @FileMap, line: uint}
    {
        let idx = self.lookup_filemap_idx(pos);
        let f = self.files[idx];
        let mut a = 0u;
        let mut b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if f.lines[m] > pos { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos(&self, +pos: BytePos) -> Loc {
        let {fm: f, line: a} = self.lookup_line(pos);
        let line = a + 1u; // Line numbers start at 1
        let chpos = self.bytepos_to_local_charpos(pos);
        let linebpos = f.lines[a];
        let linechpos = self.bytepos_to_local_charpos(linebpos);
        debug!("codemap: byte pos %? is on the line at byte pos %?",
               pos, linebpos);
        debug!("codemap: char pos %? is on the line at char pos %?",
               chpos, linechpos);
        debug!("codemap: byte is on line: %?", line);
        assert chpos >= linechpos;
        return Loc {
            file: f,
            line: line,
            col: chpos - linechpos
        };
    }

    fn span_to_str_no_adj(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    fn lookup_byte_offset(&self, +bpos: BytePos)
        -> {fm: @FileMap, pos: BytePos} {
        let idx = self.lookup_filemap_idx(bpos);
        let fm = self.files[idx];
        let offset = bpos - fm.start_pos;
        return {fm: fm, pos: offset};
    }

    // Converts an absolute BytePos to a CharPos relative to the file it is
    // located in
    fn bytepos_to_local_charpos(&self, +bpos: BytePos) -> CharPos {
        debug!("codemap: converting %? to char pos", bpos);
        let idx = self.lookup_filemap_idx(bpos);
        let map = self.files[idx];

        // The number of extra bytes due to multibyte chars in the FileMap
        let mut total_extra_bytes = 0;

        for map.multibyte_chars.each |mbc| {
            debug!("codemap: %?-byte char at %?", mbc.bytes, mbc.pos);
            if mbc.pos < bpos {
                total_extra_bytes += mbc.bytes;
                // We should never see a byte position in the middle of a
                // character
                assert bpos == mbc.pos
                    || bpos.to_uint() >= mbc.pos.to_uint() + mbc.bytes;
            } else {
                break;
            }
        }

        CharPos(bpos.to_uint() - total_extra_bytes)
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>