<commit_before>// Copyright 2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use DateDay;
use DateMonth;
use DateWeekday;
use DateYear;
use Time;
use ffi;
use ffi as glib_ffi;
use gobject_ffi;
use libc;
use std::cmp;
use std::mem;
use std::ptr;
use translate::*;

glib_wrapper! {
    pub struct Date(Boxed<ffi::GDate>);

    match fn {
        copy => |ptr| gobject_ffi::g_boxed_copy(ffi::g_date_get_type(), ptr as *const _) as *mut _,
        free => |ptr| ffi::g_date_free(ptr),
        get_type => || ffi::g_date_get_type(),
    }
}

impl Date {
    pub fn new() -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new())
        }
    }

    pub fn new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new_dmy(day, month.to_glib(), year))
        }
    }

    pub fn new_julian(julian_day: u32) -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new_julian(julian_day))
        }
    }

    pub fn add_days(&mut self, n_days: u32) {
        unsafe {
            ffi::g_date_add_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn add_months(&mut self, n_months: u32) {
        unsafe {
            ffi::g_date_add_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn add_years(&mut self, n_years: u32) {
        unsafe {
            ffi::g_date_add_years(self.to_glib_none_mut().0, n_years);
        }
    }

    pub fn clamp(&mut self, min_date: &Date, max_date: &Date) {
        unsafe {
            ffi::g_date_clamp(self.to_glib_none_mut().0, min_date.to_glib_none().0, max_date.to_glib_none().0);
        }
    }

    pub fn clear(&mut self, n_dates: u32) {
        unsafe {
            ffi::g_date_clear(self.to_glib_none_mut().0, n_dates);
        }
    }

    fn compare(&self, rhs: &Date) -> i32 {
        unsafe {
            ffi::g_date_compare(self.to_glib_none().0, rhs.to_glib_none().0)
        }
    }

    pub fn days_between(&self, date2: &Date) -> i32 {
        unsafe {
            ffi::g_date_days_between(self.to_glib_none().0, date2.to_glib_none().0)
        }
    }

    pub fn get_day(&self) -> DateDay {
        unsafe {
            ffi::g_date_get_day(self.to_glib_none().0)
        }
    }

    pub fn get_day_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_day_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_iso8601_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_iso8601_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_julian(&self) -> u32 {
        unsafe {
            ffi::g_date_get_julian(self.to_glib_none().0)
        }
    }

    pub fn get_monday_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_monday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_month(&self) -> DateMonth {
        unsafe {
            from_glib(ffi::g_date_get_month(self.to_glib_none().0))
        }
    }

    pub fn get_sunday_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_sunday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_weekday(&self) -> DateWeekday {
        unsafe {
            from_glib(ffi::g_date_get_weekday(self.to_glib_none().0))
        }
    }

    pub fn get_year(&self) -> DateYear {
        unsafe {
            ffi::g_date_get_year(self.to_glib_none().0)
        }
    }

    pub fn is_first_of_month(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_first_of_month(self.to_glib_none().0))
        }
    }

    pub fn is_last_of_month(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_last_of_month(self.to_glib_none().0))
        }
    }

    pub fn order(&mut self, date2: &mut Date) {
        unsafe {
            ffi::g_date_order(self.to_glib_none_mut().0, date2.to_glib_none_mut().0);
        }
    }

    pub fn set_day(&mut self, day: DateDay) {
        unsafe {
            ffi::g_date_set_day(self.to_glib_none_mut().0, day);
        }
    }

    pub fn set_dmy(&mut self, day: DateDay, month: DateMonth, y: DateYear) {
        unsafe {
            ffi::g_date_set_dmy(self.to_glib_none_mut().0, day, month.to_glib(), y);
        }
    }

    pub fn set_julian(&mut self, julian_date: u32) {
        unsafe {
            ffi::g_date_set_julian(self.to_glib_none_mut().0, julian_date);
        }
    }

    pub fn set_month(&mut self, month: DateMonth) {
        unsafe {
            ffi::g_date_set_month(self.to_glib_none_mut().0, month.to_glib());
        }
    }

    pub fn set_parse(&mut self, str: &str) {
        unsafe {
            ffi::g_date_set_parse(self.to_glib_none_mut().0, str.to_glib_none().0);
        }
    }

    pub fn set_time(&mut self, time_: Time) {
        unsafe {
            ffi::g_date_set_time(self.to_glib_none_mut().0, time_);
        }
    }

    pub fn set_time_t(&mut self, timet: libc::c_long) {
        unsafe {
            ffi::g_date_set_time_t(self.to_glib_none_mut().0, timet);
        }
    }

    //pub fn set_time_val(&mut self, timeval: /*Ignored*/&mut TimeVal) {
    //    unsafe { TODO: call ffi::g_date_set_time_val() }
    //}

    pub fn set_year(&mut self, year: DateYear) {
        unsafe {
            ffi::g_date_set_year(self.to_glib_none_mut().0, year);
        }
    }

    pub fn subtract_days(&mut self, n_days: u32) {
        unsafe {
            ffi::g_date_subtract_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn subtract_months(&mut self, n_months: u32) {
        unsafe {
            ffi::g_date_subtract_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn subtract_years(&mut self, n_years: u32) {
        unsafe {
            ffi::g_date_subtract_years(self.to_glib_none_mut().0, n_years);
        }
    }

    //pub fn to_struct_tm(&self, tm: /*Unimplemented*/Fundamental: Pointer) {
    //    unsafe { TODO: call ffi::g_date_to_struct_tm() }
    //}

    pub fn valid(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid(self.to_glib_none().0))
        }
    }

    pub fn get_days_in_month(month: DateMonth, year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_days_in_month(month.to_glib(), year)
        }
    }

    pub fn get_monday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_monday_weeks_in_year(year)
        }
    }

    pub fn get_sunday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_sunday_weeks_in_year(year)
        }
    }

    pub fn is_leap_year(year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_leap_year(year))
        }
    }

    pub fn strftime(s: &str, format: &str, date: &Date) -> usize {
        let slen = s.len() as usize;
        unsafe {
            ffi::g_date_strftime(s.to_glib_none().0, slen, format.to_glib_none().0, date.to_glib_none().0)
        }
    }

    pub fn valid_day(day: DateDay) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_day(day))
        }
    }

    pub fn valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_dmy(day, month.to_glib(), year))
        }
    }

    pub fn valid_julian(julian_date: u32) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_julian(julian_date))
        }
    }

    pub fn valid_month(month: DateMonth) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_month(month.to_glib()))
        }
    }

    pub fn valid_weekday(weekday: DateWeekday) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_weekday(weekday.to_glib()))
        }
    }

    pub fn valid_year(year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_year(year))
        }
    }
}

impl Default for Date {
    fn default() -> Self {
        Self::new()
    }
}

impl PartialEq for Date {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.compare(other) == 0
    }
}

impl Eq for Date {}

impl PartialOrd for Date {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.compare(other).partial_cmp(&0)
    }
}

impl Ord for Date {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.compare(other).cmp(&0)
    }
}
<commit_msg>Implement Send for GDate<commit_after>// Copyright 2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use DateDay;
use DateMonth;
use DateWeekday;
use DateYear;
use Time;
use ffi;
use ffi as glib_ffi;
use gobject_ffi;
use libc;
use std::cmp;
use std::mem;
use std::ptr;
use translate::*;

glib_wrapper! {
    pub struct Date(Boxed<ffi::GDate>);

    match fn {
        copy => |ptr| gobject_ffi::g_boxed_copy(ffi::g_date_get_type(), ptr as *const _) as *mut _,
        free => |ptr| ffi::g_date_free(ptr),
        get_type => || ffi::g_date_get_type(),
    }
}

unsafe impl Send for Date { }

impl Date {
    pub fn new() -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new())
        }
    }

    pub fn new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new_dmy(day, month.to_glib(), year))
        }
    }

    pub fn new_julian(julian_day: u32) -> Date {
        unsafe {
            from_glib_full(ffi::g_date_new_julian(julian_day))
        }
    }

    pub fn add_days(&mut self, n_days: u32) {
        unsafe {
            ffi::g_date_add_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn add_months(&mut self, n_months: u32) {
        unsafe {
            ffi::g_date_add_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn add_years(&mut self, n_years: u32) {
        unsafe {
            ffi::g_date_add_years(self.to_glib_none_mut().0, n_years);
        }
    }

    pub fn clamp(&mut self, min_date: &Date, max_date: &Date) {
        unsafe {
            ffi::g_date_clamp(self.to_glib_none_mut().0, min_date.to_glib_none().0, max_date.to_glib_none().0);
        }
    }

    pub fn clear(&mut self, n_dates: u32) {
        unsafe {
            ffi::g_date_clear(self.to_glib_none_mut().0, n_dates);
        }
    }

    fn compare(&self, rhs: &Date) -> i32 {
        unsafe {
            ffi::g_date_compare(self.to_glib_none().0, rhs.to_glib_none().0)
        }
    }

    pub fn days_between(&self, date2: &Date) -> i32 {
        unsafe {
            ffi::g_date_days_between(self.to_glib_none().0, date2.to_glib_none().0)
        }
    }

    pub fn get_day(&self) -> DateDay {
        unsafe {
            ffi::g_date_get_day(self.to_glib_none().0)
        }
    }

    pub fn get_day_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_day_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_iso8601_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_iso8601_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_julian(&self) -> u32 {
        unsafe {
            ffi::g_date_get_julian(self.to_glib_none().0)
        }
    }

    pub fn get_monday_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_monday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_month(&self) -> DateMonth {
        unsafe {
            from_glib(ffi::g_date_get_month(self.to_glib_none().0))
        }
    }

    pub fn get_sunday_week_of_year(&self) -> u32 {
        unsafe {
            ffi::g_date_get_sunday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_weekday(&self) -> DateWeekday {
        unsafe {
            from_glib(ffi::g_date_get_weekday(self.to_glib_none().0))
        }
    }

    pub fn get_year(&self) -> DateYear {
        unsafe {
            ffi::g_date_get_year(self.to_glib_none().0)
        }
    }

    pub fn is_first_of_month(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_first_of_month(self.to_glib_none().0))
        }
    }

    pub fn is_last_of_month(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_last_of_month(self.to_glib_none().0))
        }
    }

    pub fn order(&mut self, date2: &mut Date) {
        unsafe {
            ffi::g_date_order(self.to_glib_none_mut().0, date2.to_glib_none_mut().0);
        }
    }

    pub fn set_day(&mut self, day: DateDay) {
        unsafe {
            ffi::g_date_set_day(self.to_glib_none_mut().0, day);
        }
    }

    pub fn set_dmy(&mut self, day: DateDay, month: DateMonth, y: DateYear) {
        unsafe {
            ffi::g_date_set_dmy(self.to_glib_none_mut().0, day, month.to_glib(), y);
        }
    }

    pub fn set_julian(&mut self, julian_date: u32) {
        unsafe {
            ffi::g_date_set_julian(self.to_glib_none_mut().0, julian_date);
        }
    }

    pub fn set_month(&mut self, month: DateMonth) {
        unsafe {
            ffi::g_date_set_month(self.to_glib_none_mut().0, month.to_glib());
        }
    }

    pub fn set_parse(&mut self, str: &str) {
        unsafe {
            ffi::g_date_set_parse(self.to_glib_none_mut().0, str.to_glib_none().0);
        }
    }

    pub fn set_time(&mut self, time_: Time) {
        unsafe {
            ffi::g_date_set_time(self.to_glib_none_mut().0, time_);
        }
    }

    pub fn set_time_t(&mut self, timet: libc::c_long) {
        unsafe {
            ffi::g_date_set_time_t(self.to_glib_none_mut().0, timet);
        }
    }

    //pub fn set_time_val(&mut self, timeval: /*Ignored*/&mut TimeVal) {
    //    unsafe { TODO: call ffi::g_date_set_time_val() }
    //}

    pub fn set_year(&mut self, year: DateYear) {
        unsafe {
            ffi::g_date_set_year(self.to_glib_none_mut().0, year);
        }
    }

    pub fn subtract_days(&mut self, n_days: u32) {
        unsafe {
            ffi::g_date_subtract_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn subtract_months(&mut self, n_months: u32) {
        unsafe {
            ffi::g_date_subtract_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn subtract_years(&mut self, n_years: u32) {
        unsafe {
            ffi::g_date_subtract_years(self.to_glib_none_mut().0, n_years);
        }
    }

    //pub fn to_struct_tm(&self, tm: /*Unimplemented*/Fundamental: Pointer) {
    //    unsafe { TODO: call ffi::g_date_to_struct_tm() }
    //}

    pub fn valid(&self) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid(self.to_glib_none().0))
        }
    }

    pub fn get_days_in_month(month: DateMonth, year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_days_in_month(month.to_glib(), year)
        }
    }

    pub fn get_monday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_monday_weeks_in_year(year)
        }
    }

    pub fn get_sunday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            ffi::g_date_get_sunday_weeks_in_year(year)
        }
    }

    pub fn is_leap_year(year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_is_leap_year(year))
        }
    }

    pub fn strftime(s: &str, format: &str, date: &Date) -> usize {
        let slen = s.len() as usize;
        unsafe {
            ffi::g_date_strftime(s.to_glib_none().0, slen, format.to_glib_none().0, date.to_glib_none().0)
        }
    }

    pub fn valid_day(day: DateDay) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_day(day))
        }
    }

    pub fn valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_dmy(day, month.to_glib(), year))
        }
    }

    pub fn valid_julian(julian_date: u32) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_julian(julian_date))
        }
    }

    pub fn valid_month(month: DateMonth) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_month(month.to_glib()))
        }
    }

    pub fn valid_weekday(weekday: DateWeekday) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_weekday(weekday.to_glib()))
        }
    }

    pub fn valid_year(year: DateYear) -> bool {
        unsafe {
            from_glib(ffi::g_date_valid_year(year))
        }
    }
}

impl Default for Date {
    fn default() -> Self {
        Self::new()
    }
}

impl PartialEq for Date {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.compare(other) == 0
    }
}

impl Eq for Date {}

impl PartialOrd for Date {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.compare(other).partial_cmp(&0)
    }
}

impl Ord for Date {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.compare(other).cmp(&0)
    }
}
<|endoftext|>


<commit_before>use std::{fs, io, path};
use hex::FromHex;

// cannot be generic, because from_str_radix is not part of any Trait
fn parse_raw(bytes: &[u8], radix: u32) -> Option<u64> {
    ::std::str::from_utf8(bytes)
        .ok()
        .and_then(|s| u64::from_str_radix(s, radix).ok())
}

#[derive(Debug)]
pub struct Reader<R> {
    rdr: R,
    line_buf: Vec<u8>,
}

impl<R: io::Read> Reader<R> {
    pub fn from_reader(rdr: R) -> Reader<io::BufReader<R>> {
        Reader {
            rdr: io::BufReader::new(rdr),
            line_buf: Vec::new(),
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<path::Path>>(path: P) -> io::Result<Reader<io::BufReader<fs::File>>> {
        Ok(Reader::from_reader(try!(fs::File::open(path))))
    }
}

#[derive(Debug)]
pub struct CanDumpRecords<'a, R: 'a> {
    src: &'a mut Reader<R>,
}

#[derive(Debug)]
pub struct CanDumpRecord<'a> {
    pub t_us: u64,
    pub device: &'a str,
    pub frame: super::CANFrame,
}

#[derive(Debug)]
pub enum ParseError {
    Io(io::Error),
    UnexpectedEndOfLine,
    InvalidTimestamp,
    InvalidDeviceName,
    InvalidCanFrame,
    ConstructionError(super::ConstructionError),
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> ParseError {
        ParseError::Io(e)
    }
}

impl From<super::ConstructionError> for ParseError {
    fn from(e: super::ConstructionError) -> ParseError {
        ParseError::ConstructionError(e)
    }
}

impl<R: io::BufRead> Reader<R> {
    pub fn records<'a>(&'a mut self) -> CanDumpRecords<'a, R> {
        CanDumpRecords { src: self }
    }

    pub fn next_record(&mut self) -> Result<Option<CanDumpRecord>, ParseError> {
        self.line_buf.clear();
        let bytes_read = try!(self.rdr.read_until(b'\n', &mut self.line_buf));

        // reached EOF
        if bytes_read == 0 {
            return Ok(None);
        }

        let mut field_iter = self.line_buf.split(|&c| c == b' ');

        // parse time field
        let f = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        if f.len() < 3 || f[0] != b'(' || f[f.len() - 1] != b')' {
            return Err(ParseError::InvalidTimestamp);
        }

        let inner = &f[1..f.len() - 1];

        // split at dot, read both parts
        let dot = try!(inner.iter()
            .position(|&c| c == b'.')
            .ok_or(ParseError::InvalidTimestamp));

        let (num, mant) = inner.split_at(dot);

        // parse number and multiply
        let n_num: u64 = try!(parse_raw(num, 10).ok_or(ParseError::InvalidTimestamp));
        let n_mant: u64 = try!(parse_raw(&mant[1..], 10).ok_or(ParseError::InvalidTimestamp));
        let t_us = n_num.saturating_mul(1_000_000).saturating_add(n_mant);

        let f = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        // device name
        let device = try!(::std::str::from_utf8(f).map_err(|_| ParseError::InvalidDeviceName));

        // parse packet
        let can_raw = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        let sep_idx =
            try!(can_raw.iter().position(|&c| c == b'#').ok_or(ParseError::InvalidCanFrame));
        let (can_id, mut can_data) = can_raw.split_at(sep_idx);

        // cut of linefeed and skip seperator
        can_data = &can_data[1..];
        if let Some(&b'\n') = can_data.last() {
            can_data = &can_data[..can_data.len() - 1];
        };

        let rtr = b"R" == can_data;

        let data = if rtr {
            Vec::new()
        } else {
            try!(Vec::from_hex(&can_data).map_err(|_| ParseError::InvalidCanFrame))
        };
        let frame = try!(super::CANFrame::new(try!(parse_raw(can_id, 16)
                                                  .ok_or

                                                  (ParseError::InvalidCanFrame))
                                              as u32,
                                              &data,
                                              rtr,
                                              // FIXME: how are error frames saved?
                                              false));

        Ok(Some(CanDumpRecord {
            t_us: t_us,
            device: device,
            frame: frame,
        }))
    }
}

impl<'a, R: io::Read> Iterator for CanDumpRecords<'a, io::BufReader<R>> {
    type Item = Result<(u64, super::CANFrame), ParseError>;

    fn next(&mut self) -> Option<Self::Item> {
        // lift Option:
        match self.src.next_record() {
            Ok(Some(CanDumpRecord { t_us, frame, .. })) => Some(Ok((t_us, frame))),
            Ok(None) => None,
            Err(e) => Some(Err(e)),
        }
    }
}

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

    #[test]
    fn test_simple_example() {
        let input: &[u8] = b"(1469439874.299591) can1 080#\n\
                             (1469439874.299654) can1 701#7F";

        let mut reader = Reader::from_reader(input);

        {
            let rec1 = reader.next_record().unwrap().unwrap();

            assert_eq!(rec1.t_us, 1469439874299591);
            assert_eq!(rec1.device, "can1");
            assert_eq!(rec1.frame.id(), 0x080);
            assert_eq!(rec1.frame.is_rtr(), false);
            assert_eq!(rec1.frame.is_error(), false);
            assert_eq!(rec1.frame.is_extended(), false);
            assert_eq!(rec1.frame.data(), &[]);
        }

        {
            let rec2 = reader.next_record().unwrap().unwrap();
            assert_eq!(rec2.t_us, 1469439874299654);
            assert_eq!(rec2.device, "can1");
            assert_eq!(rec2.frame.id(), 0x701);
            assert_eq!(rec2.frame.is_rtr(), false);
            assert_eq!(rec2.frame.is_error(), false);
            assert_eq!(rec2.frame.is_extended(), false);
            assert_eq!(rec2.frame.data(), &[0x7F]);
        }

        assert!(reader.next_record().unwrap().is_none());
    }

}
<commit_msg>Added docs for dump module.<commit_after>//! candump format parsing
//!
//! Parses the text format emitted by the `candump` utility, which is part of
//! [can-utils](https://github.com/linux-can/can-utils).
//!
//! Example:
//!
//! ```text
//! (1469439874.299654) can1 701#7F
//! ```
//!
//! Can be parsed by a `Reader` object. The API is inspired by the
//! [csv](https://crates.io/crates/csv) crate.

use std::{fs, io, path};
use hex::FromHex;

// cannot be generic, because from_str_radix is not part of any Trait
fn parse_raw(bytes: &[u8], radix: u32) -> Option<u64> {
    ::std::str::from_utf8(bytes)
        .ok()
        .and_then(|s| u64::from_str_radix(s, radix).ok())
}

#[derive(Debug)]
/// A CAN log reader.
pub struct Reader<R> {
    rdr: R,
    line_buf: Vec<u8>,
}

impl<R: io::Read> Reader<R> {
    pub fn from_reader(rdr: R) -> Reader<io::BufReader<R>> {
        Reader {
            rdr: io::BufReader::new(rdr),
            line_buf: Vec::new(),
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<path::Path>>(path: P) -> io::Result<Reader<io::BufReader<fs::File>>> {
        Ok(Reader::from_reader(try!(fs::File::open(path))))
    }
}

/// Record iterator
#[derive(Debug)]
pub struct CanDumpRecords<'a, R: 'a> {
    src: &'a mut Reader<R>,
}

/// Recorded CAN frame.
#[derive(Debug)]
pub struct CanDumpRecord<'a> {
    pub t_us: u64,
    pub device: &'a str,
    pub frame: super::CANFrame,
}

#[derive(Debug)]
/// candump line parse error
pub enum ParseError {
    Io(io::Error),
    UnexpectedEndOfLine,
    InvalidTimestamp,
    InvalidDeviceName,
    InvalidCanFrame,
    ConstructionError(super::ConstructionError),
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> ParseError {
        ParseError::Io(e)
    }
}

impl From<super::ConstructionError> for ParseError {
    fn from(e: super::ConstructionError) -> ParseError {
        ParseError::ConstructionError(e)
    }
}

impl<R: io::BufRead> Reader<R> {
    /// Returns an iterator over all records
    pub fn records<'a>(&'a mut self) -> CanDumpRecords<'a, R> {
        CanDumpRecords { src: self }
    }

    /// Advance state, returning next record.
    pub fn next_record(&mut self) -> Result<Option<CanDumpRecord>, ParseError> {
        self.line_buf.clear();
        let bytes_read = try!(self.rdr.read_until(b'\n', &mut self.line_buf));

        // reached EOF
        if bytes_read == 0 {
            return Ok(None);
        }

        let mut field_iter = self.line_buf.split(|&c| c == b' ');

        // parse time field
        let f = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        if f.len() < 3 || f[0] != b'(' || f[f.len() - 1] != b')' {
            return Err(ParseError::InvalidTimestamp);
        }

        let inner = &f[1..f.len() - 1];

        // split at dot, read both parts
        let dot = try!(inner.iter()
            .position(|&c| c == b'.')
            .ok_or(ParseError::InvalidTimestamp));

        let (num, mant) = inner.split_at(dot);

        // parse number and multiply
        let n_num: u64 = try!(parse_raw(num, 10).ok_or(ParseError::InvalidTimestamp));
        let n_mant: u64 = try!(parse_raw(&mant[1..], 10).ok_or(ParseError::InvalidTimestamp));
        let t_us = n_num.saturating_mul(1_000_000).saturating_add(n_mant);

        let f = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        // device name
        let device = try!(::std::str::from_utf8(f).map_err(|_| ParseError::InvalidDeviceName));

        // parse packet
        let can_raw = try!(field_iter.next().ok_or(ParseError::UnexpectedEndOfLine));

        let sep_idx =
            try!(can_raw.iter().position(|&c| c == b'#').ok_or(ParseError::InvalidCanFrame));
        let (can_id, mut can_data) = can_raw.split_at(sep_idx);

        // cut of linefeed and skip seperator
        can_data = &can_data[1..];
        if let Some(&b'\n') = can_data.last() {
            can_data = &can_data[..can_data.len() - 1];
        };

        let rtr = b"R" == can_data;

        let data = if rtr {
            Vec::new()
        } else {
            try!(Vec::from_hex(&can_data).map_err(|_| ParseError::InvalidCanFrame))
        };
        let frame = try!(super::CANFrame::new(try!(parse_raw(can_id, 16)
                                                  .ok_or

                                                  (ParseError::InvalidCanFrame))
                                              as u32,
                                              &data,
                                              rtr,
                                              // FIXME: how are error frames saved?
                                              false));

        Ok(Some(CanDumpRecord {
            t_us: t_us,
            device: device,
            frame: frame,
        }))
    }
}

impl<'a, R: io::Read> Iterator for CanDumpRecords<'a, io::BufReader<R>> {
    type Item = Result<(u64, super::CANFrame), ParseError>;

    fn next(&mut self) -> Option<Self::Item> {
        // lift Option:
        match self.src.next_record() {
            Ok(Some(CanDumpRecord { t_us, frame, .. })) => Some(Ok((t_us, frame))),
            Ok(None) => None,
            Err(e) => Some(Err(e)),
        }
    }
}

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

    #[test]
    fn test_simple_example() {
        let input: &[u8] = b"(1469439874.299591) can1 080#\n\
                             (1469439874.299654) can1 701#7F";

        let mut reader = Reader::from_reader(input);

        {
            let rec1 = reader.next_record().unwrap().unwrap();

            assert_eq!(rec1.t_us, 1469439874299591);
            assert_eq!(rec1.device, "can1");
            assert_eq!(rec1.frame.id(), 0x080);
            assert_eq!(rec1.frame.is_rtr(), false);
            assert_eq!(rec1.frame.is_error(), false);
            assert_eq!(rec1.frame.is_extended(), false);
            assert_eq!(rec1.frame.data(), &[]);
        }

        {
            let rec2 = reader.next_record().unwrap().unwrap();
            assert_eq!(rec2.t_us, 1469439874299654);
            assert_eq!(rec2.device, "can1");
            assert_eq!(rec2.frame.id(), 0x701);
            assert_eq!(rec2.frame.is_rtr(), false);
            assert_eq!(rec2.frame.is_error(), false);
            assert_eq!(rec2.frame.is_extended(), false);
            assert_eq!(rec2.frame.data(), &[0x7F]);
        }

        assert!(reader.next_record().unwrap().is_none());
    }

}
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2015 by
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # ECDH
//! Support for shared secret computations
//!

use core::ptr;
use core::ops::{FnMut, Deref};

use key::{SecretKey, PublicKey};
use ffi::{self, CPtr};
use secp256k1_sys::types::{c_int, c_uchar, c_void};

/// A tag used for recovering the public key from a compact signature
#[derive(Copy, Clone)]
pub struct SharedSecret {
    data: [u8; 256],
    len: usize,
}
impl_raw_debug!(SharedSecret);

// This implementes `From<N>` for all `[u8; N]` arrays from 128bits(16 byte) to 2048bits allowing known hash lengths.
// Lower than 128 bits isn't resistant to collisions any more.
impl_from_array_len!(SharedSecret, 256, (16 20 28 32 48 64 96 128 256));

impl SharedSecret {

    /// Create an empty SharedSecret
    pub(crate) fn empty() ->  SharedSecret {
        SharedSecret {
            data: [0u8; 256],
            len: 0,
        }
    }

    /// Get a pointer to the underlying data with the specified capacity.
    pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 {
        self.data.as_mut_ptr()
    }

    /// Get the capacity of the underlying data buffer.
    pub fn capacity(&self) -> usize {
        self.data.len()
    }

    /// Get the len of the used data.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Set the length of the object.
    pub(crate) fn set_len(&mut self, len: usize) {
        self.len = len;
    }
}

impl PartialEq for SharedSecret {
    fn eq(&self, other: &SharedSecret) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl AsRef<[u8]> for SharedSecret {
    fn as_ref(&self) -> &[u8] {
        &self.data[..self.len]
    }
}

impl Deref for SharedSecret {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &self.data[..self.len]
    }
}

unsafe extern "C" fn hash_callback<F>(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, data: *mut c_void) -> c_int
    where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret {
    let callback: &mut F = &mut *(data as *mut F);

    let mut x_arr = [0; 32];
    let mut y_arr = [0; 32];
    ptr::copy_nonoverlapping(x, x_arr.as_mut_ptr(), 32);
    ptr::copy_nonoverlapping(y, y_arr.as_mut_ptr(), 32);

    let secret = callback(x_arr, y_arr);
    ptr::copy_nonoverlapping(secret.as_ptr(), output as *mut u8, secret.len());

    secret.len() as c_int
}

impl SharedSecret {
    /// Creates a new shared secret from a pubkey and secret key
    #[inline]
    pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
        let mut ss = SharedSecret::empty();
        let res = unsafe {
             ffi::secp256k1_ecdh(
                ffi::secp256k1_context_no_precomp,
                ss.get_data_mut_ptr(),
                point.as_c_ptr(),
                scalar.as_c_ptr(),
                ffi::secp256k1_ecdh_hash_function_default,
                ptr::null_mut(),
            )
        };
        debug_assert_eq!(res, 1); // The default `secp256k1_ecdh_hash_function_default` should always return 1.
        ss.set_len(32); // The default hash function is SHA256, which is 32 bytes long.
        ss
    }

    /// Creates a new shared secret from a pubkey and secret key with applied custom hash function
    /// # Examples
    /// ```
    /// # use secp256k1::ecdh::SharedSecret;
    /// # use secp256k1::{Secp256k1, PublicKey, SecretKey};
    /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]}
    /// # let secp = Secp256k1::signing_only();
    /// # let secret_key = SecretKey::from_slice(&[3u8; 32]).unwrap();
    /// # let secret_key2 = SecretKey::from_slice(&[7u8; 32]).unwrap();
    /// # let public_key = PublicKey::from_secret_key(&secp, &secret_key2);
    ///
    /// let secret = SharedSecret::new_with_hash(&public_key, &secret_key, |x,y| {
    ///     let hash: [u8; 32] = sha2(&x,&y);
    ///     hash.into()
    /// });
    ///
    /// ```
    pub fn new_with_hash<F>(point: &PublicKey, scalar: &SecretKey, mut hash_function: F) -> SharedSecret
        where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret
    {
        let mut ss = SharedSecret::empty();
        let hashfp: ffi::EcdhHashFn = hash_callback::<F>;

        let res =  unsafe {
            ffi::secp256k1_ecdh(
                ffi::secp256k1_context_no_precomp,
                ss.get_data_mut_ptr(),
                point.as_ptr(),
                scalar.as_ptr(),
                hashfp,
                &mut hash_function as *mut F as *mut c_void,
            )
        };
        debug_assert!(res >= 16); // 128 bit is the minimum for a secure hash function and the minimum we let users.
        ss.set_len(res as usize);
        ss
    }
}

#[cfg(test)]
mod tests {
    use rand::thread_rng;
    use super::SharedSecret;
    use super::super::Secp256k1;

    #[test]
    fn ecdh() {
        let s = Secp256k1::signing_only();
        let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
        let (sk2, pk2) = s.generate_keypair(&mut thread_rng());

        let sec1 = SharedSecret::new(&pk1, &sk2);
        let sec2 = SharedSecret::new(&pk2, &sk1);
        let sec_odd = SharedSecret::new(&pk1, &sk1);
        assert_eq!(sec1, sec2);
        assert!(sec_odd != sec2);
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use rand::thread_rng;
    use test::{Bencher, black_box};

    use super::SharedSecret;
    use super::super::Secp256k1;

    #[bench]
    pub fn bench_ecdh(bh: &mut Bencher) {
        let s = Secp256k1::signing_only();
        let (sk, pk) = s.generate_keypair(&mut thread_rng());

        let s = Secp256k1::new();
        bh.iter( || {
            let res = SharedSecret::new(&pk, &sk);
            black_box(res);
        });
    }
}

<commit_msg>Add tests for the new SharedSecret::new_with_hash() function<commit_after>// Bitcoin secp256k1 bindings
// Written in 2015 by
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # ECDH
//! Support for shared secret computations
//!

use core::ptr;
use core::ops::{FnMut, Deref};

use key::{SecretKey, PublicKey};
use ffi::{self, CPtr};
use secp256k1_sys::types::{c_int, c_uchar, c_void};

/// A tag used for recovering the public key from a compact signature
#[derive(Copy, Clone)]
pub struct SharedSecret {
    data: [u8; 256],
    len: usize,
}
impl_raw_debug!(SharedSecret);

// This implementes `From<N>` for all `[u8; N]` arrays from 128bits(16 byte) to 2048bits allowing known hash lengths.
// Lower than 128 bits isn't resistant to collisions any more.
impl_from_array_len!(SharedSecret, 256, (16 20 28 32 48 64 96 128 256));

impl SharedSecret {

    /// Create an empty SharedSecret
    pub(crate) fn empty() ->  SharedSecret {
        SharedSecret {
            data: [0u8; 256],
            len: 0,
        }
    }

    /// Get a pointer to the underlying data with the specified capacity.
    pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 {
        self.data.as_mut_ptr()
    }

    /// Get the capacity of the underlying data buffer.
    pub fn capacity(&self) -> usize {
        self.data.len()
    }

    /// Get the len of the used data.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Set the length of the object.
    pub(crate) fn set_len(&mut self, len: usize) {
        self.len = len;
    }
}

impl PartialEq for SharedSecret {
    fn eq(&self, other: &SharedSecret) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl AsRef<[u8]> for SharedSecret {
    fn as_ref(&self) -> &[u8] {
        &self.data[..self.len]
    }
}

impl Deref for SharedSecret {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &self.data[..self.len]
    }
}

unsafe extern "C" fn hash_callback<F>(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, data: *mut c_void) -> c_int
    where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret {
    let callback: &mut F = &mut *(data as *mut F);

    let mut x_arr = [0; 32];
    let mut y_arr = [0; 32];
    ptr::copy_nonoverlapping(x, x_arr.as_mut_ptr(), 32);
    ptr::copy_nonoverlapping(y, y_arr.as_mut_ptr(), 32);

    let secret = callback(x_arr, y_arr);
    ptr::copy_nonoverlapping(secret.as_ptr(), output as *mut u8, secret.len());

    secret.len() as c_int
}

impl SharedSecret {
    /// Creates a new shared secret from a pubkey and secret key
    #[inline]
    pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
        let mut ss = SharedSecret::empty();
        let res = unsafe {
             ffi::secp256k1_ecdh(
                ffi::secp256k1_context_no_precomp,
                ss.get_data_mut_ptr(),
                point.as_c_ptr(),
                scalar.as_c_ptr(),
                ffi::secp256k1_ecdh_hash_function_default,
                ptr::null_mut(),
            )
        };
        debug_assert_eq!(res, 1); // The default `secp256k1_ecdh_hash_function_default` should always return 1.
        ss.set_len(32); // The default hash function is SHA256, which is 32 bytes long.
        ss
    }

    /// Creates a new shared secret from a pubkey and secret key with applied custom hash function
    /// # Examples
    /// ```
    /// # use secp256k1::ecdh::SharedSecret;
    /// # use secp256k1::{Secp256k1, PublicKey, SecretKey};
    /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]}
    /// # let secp = Secp256k1::signing_only();
    /// # let secret_key = SecretKey::from_slice(&[3u8; 32]).unwrap();
    /// # let secret_key2 = SecretKey::from_slice(&[7u8; 32]).unwrap();
    /// # let public_key = PublicKey::from_secret_key(&secp, &secret_key2);
    ///
    /// let secret = SharedSecret::new_with_hash(&public_key, &secret_key, |x,y| {
    ///     let hash: [u8; 32] = sha2(&x,&y);
    ///     hash.into()
    /// });
    ///
    /// ```
    pub fn new_with_hash<F>(point: &PublicKey, scalar: &SecretKey, mut hash_function: F) -> SharedSecret
        where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret
    {
        let mut ss = SharedSecret::empty();
        let hashfp: ffi::EcdhHashFn = hash_callback::<F>;

        let res =  unsafe {
            ffi::secp256k1_ecdh(
                ffi::secp256k1_context_no_precomp,
                ss.get_data_mut_ptr(),
                point.as_ptr(),
                scalar.as_ptr(),
                hashfp,
                &mut hash_function as *mut F as *mut c_void,
            )
        };
        debug_assert!(res >= 16); // 128 bit is the minimum for a secure hash function and the minimum we let users.
        ss.set_len(res as usize);
        ss
    }
}

#[cfg(test)]
mod tests {
    use rand::thread_rng;
    use super::SharedSecret;
    use super::super::Secp256k1;

    #[test]
    fn ecdh() {
        let s = Secp256k1::signing_only();
        let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
        let (sk2, pk2) = s.generate_keypair(&mut thread_rng());

        let sec1 = SharedSecret::new(&pk1, &sk2);
        let sec2 = SharedSecret::new(&pk2, &sk1);
        let sec_odd = SharedSecret::new(&pk1, &sk1);
        assert_eq!(sec1, sec2);
        assert!(sec_odd != sec2);
    }

    #[test]
    fn ecdh_with_hash() {
        let s = Secp256k1::signing_only();
        let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
        let (sk2, pk2) = s.generate_keypair(&mut thread_rng());

        let sec1 = SharedSecret::new_with_hash(&pk1, &sk2, |x,_| x.into());
        let sec2 = SharedSecret::new_with_hash(&pk2, &sk1, |x,_| x.into());
        let sec_odd = SharedSecret::new_with_hash(&pk1, &sk1, |x,_| x.into());
        assert_eq!(sec1, sec2);
        assert_ne!(sec_odd, sec2);
    }

    #[test]
    fn ecdh_with_hash_callback() {
        let s = Secp256k1::signing_only();
        let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
        let expect_result: [u8; 64] = [123; 64];
        let mut x_out = [0u8; 32];
        let mut y_out = [0u8; 32];
        let result = SharedSecret::new_with_hash(&pk1, &sk1, | x, y | {
            x_out = x;
            y_out = y;
            expect_result.into()
        });
        assert_eq!(&expect_result[..], &result[..]);
        assert_ne!(x_out, [0u8; 32]);
        assert_ne!(y_out, [0u8; 32]);
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use rand::thread_rng;
    use test::{Bencher, black_box};

    use super::SharedSecret;
    use super::super::Secp256k1;

    #[bench]
    pub fn bench_ecdh(bh: &mut Bencher) {
        let s = Secp256k1::signing_only();
        let (sk, pk) = s.generate_keypair(&mut thread_rng());

        let s = Secp256k1::new();
        bh.iter( || {
            let res = SharedSecret::new(&pk, &sk);
            black_box(res);
        });
    }
}

<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use ast::*;
use env::*;
use parser::*;

pub struct Evaler {
    parser: Parser,
    env:    Rc<RefCell<Env>>
}

#[allow(dead_code)]
impl Evaler {
    pub fn new() -> Evaler {
        let mut env = Env::new();
        Evaler {
            parser: Parser::new(),
            env:    Rc::new(RefCell::new(env))
        }
    }

    pub fn eval(&mut self, code: String) -> Option<ExprAst> {
        self.parser.load(code);
        let mut res = None;
        loop {
            let exp = self.parser.read_exp();
            match exp {
                Some(_exp) => {
                    let r = self.eval_exp(_exp);
                    r.print();
                    res = Some(r);
                },
                None => break
            }
        }
        res
    }

    fn eval_exp(&mut self, exp: ExprAst) -> ExprAst {
        if exp.is_self() {
            return exp;
        } else if exp.is_symbol() {
            return self.env.clone().borrow().lookup(exp).unwrap();
        } else if exp.is_quote() {
            return exp.cdr().car();
        } else if exp.is_assign() {
            return self.eval_assign(exp);
        } else if exp.is_def() {
            return self.eval_def(exp);
        } else if exp.is_begin() {
            return self.eval_begin(exp);
        } else if exp.is_if() {
            return self.eval_if(exp);
        } else if exp.is_lambda() {
            return self.eval_lambda(exp);
        } else if exp.is_and() {
            return self.eval_and(exp);
        } else if exp.is_or() {
            return self.eval_or(exp);
        } else if exp.is_cond() {
            return self.eval_cond(exp);
        } else if exp.is_let() {
            return self.eval_let(exp);
        } else if exp.is_pair() { //app
            return self.eval_app(exp);
        }
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_assign(&mut self, exp: ExprAst) -> ExprAst {
        let var = exp.c("da");
        let val = self.eval_exp(exp.c("dda"));
        self.env.clone().borrow_mut().def_var(var, val);
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_def(&mut self, exp: ExprAst) -> ExprAst {
        let var = exp.def_var();
        let val = exp.def_val();
        let val = self.eval_exp(val);
        self.env.clone().borrow_mut().def_var(var, val);
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_if(&mut self, exp: ExprAst) -> ExprAst {
        let pred = exp.c("da");
        let blk_t = exp.c("dda");
        let blk_f = exp.c("ddd");
        let res = self.eval_exp(pred);
        if res.is_true() {
            self.eval_exp(blk_t)
        } else {
            if res.is_empty() {
                ExprAst::Bool(BoolNode::new(false))
            } else {
                self.eval_exp(blk_f.car())
            }
        }
    }

    fn eval_and(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return ExprAst::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_false() {
                return ExprAst::Bool(BoolNode::new(false));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_or(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return ExprAst::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_true() {
                return ExprAst::Bool(BoolNode::new(true));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_cond(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr().car();
        loop {
            if elems.is_empty() { break; }
            let cur = elems.car();
            let val = self.eval_exp(cur.clone());
            if val.is_true() || val == ExprAst::Symbol(SymbolNode::new("else")) {
                return self.eval_exp(cur.clone().cdr().car());
            }
            elems = elems.cdr();
        }
        ExprAst::Bool(BoolNode::new(true))
    }

    fn eval_let(&mut self, exp: ExprAst) -> ExprAst {
        fn bind_params(exp: ExprAst) -> ExprAst {
            if exp.is_empty() {
                ExprAst::Nil
            } else {
                ExprAst::Pair(PairNode::new(exp.c("aa"), bind_params(exp.cdr())))
            }
        }

        fn bind_args(exp: ExprAst) -> ExprAst {
            if exp.is_empty() {
                ExprAst::Nil
            } else {
                ExprAst::Pair(PairNode::new(exp.c("ada"), bind_args(exp.cdr())))
            }
        }

        let bindings = exp.c("da");
        bindings.print();
        let obj = ExprAst::Pair(PairNode::new(
            bind_params(bindings.clone()).make_lambda(exp.c("dd")),
            bind_args(bindings)));
        self.eval_exp(obj)
    }

    fn eval_begin(&mut self, exp: ExprAst) -> ExprAst {
        let mut _exp = exp.cdr();
        loop {
            if _exp.is_last() { break; }
            self.eval_exp(_exp.car());
            _exp = _exp.cdr();
        }
        self.eval_exp(_exp.car())
    }

    fn eval_values(&mut self, exprs: ExprAst) -> ExprAst {
        if exprs.is_empty() {
            ExprAst::Nil
        } else {
            let first = self.eval_exp(exprs.car());
            ExprAst::Pair(PairNode::new(first, self.eval_values(exprs.cdr())))
        }
    }

    fn eval_app(&mut self, expr: ExprAst) -> ExprAst {
        let _proc = self.eval_exp(expr.car());
        let _args = self.eval_values(expr.cdr());
        if _proc.is_proc() {
            let func = _proc.as_proc().func();
            return func(_args);
        } else {
            assert!(_proc.is_cproc());
            let _vars = _proc.params();
            self.env = self.env.clone().borrow_mut().extend(_vars, _args);
            let begin = ExprAst::Symbol(SymbolNode::new("begin"));
            let res = self.eval_exp(ExprAst::Pair(PairNode::new(begin, _proc.body())));
            self.env = self.env.clone().borrow_mut().parent().unwrap();
            res
        }
    }

    fn eval_lambda(&mut self, expr: ExprAst) -> ExprAst {
        ExprAst::CompProc(CompProcNode::new(expr.c("da"),  //vars
                                            expr.c("dd"),  //body
                                            self.env.clone()))
    }
}

#[test]
fn test_evaler() {
    macro_rules! test_case {
        ($test_str:expr, $expect_type:ident, $expect_val:expr) => { {
            let mut evaler = Evaler::new();
            let res = evaler.eval($test_str.to_string()).unwrap();
            if res.$expect_type() != $expect_val {
                assert!(false);
            }
        }}
    }
    test_case!("11", as_int, 11);
    test_case!("'a", as_str, "a");
    test_case!(r#""hello""#, as_str, "hello");
    test_case!("#t", as_bool, true);
    test_case!("(and #t #t)", as_bool, true);
    test_case!("(and #t #f)", as_bool, false);
    test_case!("(or #t #t)", as_bool, true);
    test_case!("(or #f #f)", as_bool, false);
    test_case!("(or #t #f)", as_bool, true);
    test_case!("(set! a 1)", as_str, "OK");
    test_case!("(integer? 1)", as_bool, true);
    test_case!("(boolean? #t)", as_bool, true);
    test_case!("(boolean? #f)", as_bool, true);
    test_case!("(integer? #t)", as_bool, false);
    test_case!("(+ 1 1)", as_int, 2);
    test_case!("(- 1 1)", as_int, 0);
    test_case!("(+ 1 1  1)", as_int, 3);
    test_case!("(+ 1 1 -1 -1)", as_int, 0);
    test_case!("(/ 2 1)", as_int, 2);
    test_case!("(* 2 2)", as_int, 4);
    test_case!("(> 2 1)", as_bool, true);
    test_case!("(> 1 2)", as_bool, false);
    test_case!("(> 1 1)", as_bool, false);
    test_case!("(- (+ 3 (* 8 5)) 1)", as_int, 42);
    test_case!("(eq? 1 1)", as_bool, true);
    test_case!("(eq? 1 2)", as_bool, false);
    test_case!("(eq? 1 #f)", as_bool, false);
    test_case!("(pair? '())", as_bool, true);
    test_case!("(> (+ 1 1) 0)", as_bool, true);
    test_case!("(if (> 1 0) 1 else 2)", as_int, 1);
    test_case!("(begin (set! a 1) a)", as_int, 1);
    test_case!("(let ((a 1)) (+ a 1))", as_int, 2);
    test_case!("(let ((a 1)) (> (+ a 1) 0))", as_bool, true);
    test_case!("(let ((a 1) (b 2)) (> a b))", as_bool, false);
    test_case!("(define (add a b) (+ a b))", as_str, "OK");
    test_case!("(cond ((eq? 1 1) 1) ((> 1 2) 2) ))", as_int, 1);
    test_case!("(begin (set! x 5) (set! x 4) (+ x 1))", as_int, 5);
    test_case!("(car '(1 2))", as_int, 1);
    test_case!("(car (cdr '(1 2)))", as_int, 2);
    test_case!("(car (cons 1 2))", as_int, 1);
    test_case!("(car (cons (pair? '(1)) pair? '()))", as_bool, true);
    test_case!("(car (cdr (cons 1 2)))", as_int, 2);
    test_case!("(car (car (cons (cons 2 3) (cons 1 2))))", as_int, 2);
    test_case!("((lambda (x) x) 1)", as_int, 1);
    test_case!("((lambda (x y) (+ x y )) 1 2)", as_int, 3);
    test_case!("(define add4 (let ((x 4)) (lambda (y) (+ x y))))", as_str, "OK");
    test_case!("(begin 1 2)", as_int, 2);
    test_case!("((lambda (x) x) 5)", as_int, 5);
    test_case!("(let ((fu (lambda (x) (+ x 1)))) (fu 1))", as_int, 2);
    test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
                (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2);
}
<commit_msg>indent<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use ast::*;
use env::*;
use parser::*;

pub struct Evaler {
    parser: Parser,
    env:    Rc<RefCell<Env>>
}

#[allow(dead_code)]
impl Evaler {
    pub fn new() -> Evaler {
        let mut env = Env::new();
        Evaler {
            parser: Parser::new(),
            env:    Rc::new(RefCell::new(env))
        }
    }

    pub fn eval(&mut self, code: String) -> Option<ExprAst> {
        self.parser.load(code);
        let mut res = None;
        loop {
            let exp = self.parser.read_exp();
            match exp {
                Some(_exp) => {
                    let r = self.eval_exp(_exp);
                    r.print();
                    res = Some(r);
                },
                None => break
            }
        }
        res
    }

    fn eval_exp(&mut self, exp: ExprAst) -> ExprAst {
        if exp.is_self() { return exp;}
        else if exp.is_symbol() { return self.env.clone().borrow().lookup(exp).unwrap();}
        else if exp.is_quote()  { return exp.cdr().car(); }
        else if exp.is_assign() { return self.eval_assign(exp); }
        else if exp.is_def()    { return self.eval_def(exp); }
        else if exp.is_begin()  { return self.eval_begin(exp); }
        else if exp.is_if()     { return self.eval_if(exp); }
        else if exp.is_lambda() { return self.eval_lambda(exp); }
        else if exp.is_and()    { return self.eval_and(exp); }
        else if exp.is_or()     { return self.eval_or(exp); }
        else if exp.is_cond()   { return self.eval_cond(exp); }
        else if exp.is_let()    { return self.eval_let(exp); }
        else if exp.is_pair()   { return self.eval_app(exp);}
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_assign(&mut self, exp: ExprAst) -> ExprAst {
        let var = exp.c("da");
        let val = self.eval_exp(exp.c("dda"));
        self.env.clone().borrow_mut().def_var(var, val);
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_def(&mut self, exp: ExprAst) -> ExprAst {
        let var = exp.def_var();
        let val = exp.def_val();
        let val = self.eval_exp(val);
        self.env.clone().borrow_mut().def_var(var, val);
        ExprAst::Symbol(SymbolNode::new("OK"))
    }

    fn eval_if(&mut self, exp: ExprAst) -> ExprAst {
        let pred = exp.c("da");
        let blk_t = exp.c("dda");
        let blk_f = exp.c("ddd");
        let res = self.eval_exp(pred);
        if res.is_true() {
            self.eval_exp(blk_t)
        } else {
            if res.is_empty() {
                ExprAst::Bool(BoolNode::new(false))
            } else {
                self.eval_exp(blk_f.car())
            }
        }
    }

    fn eval_and(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return ExprAst::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_false() {
                return ExprAst::Bool(BoolNode::new(false));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_or(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr();
        if elems.is_empty() {
            return ExprAst::Bool(BoolNode::new(true));
        }
        loop {
            if elems.is_last() { break; }
            let res = self.eval_exp(elems.car());
            if res.is_true() {
                return ExprAst::Bool(BoolNode::new(true));
            }
            elems = elems.cdr();
        }
        self.eval_exp(elems.car())
    }

    fn eval_cond(&mut self, exp: ExprAst) -> ExprAst {
        let mut elems = exp.cdr().car();
        loop {
            if elems.is_empty() { break; }
            let cur = elems.car();
            let val = self.eval_exp(cur.clone());
            if val.is_true() || val == ExprAst::Symbol(SymbolNode::new("else")) {
                return self.eval_exp(cur.clone().cdr().car());
            }
            elems = elems.cdr();
        }
        ExprAst::Bool(BoolNode::new(true))
    }

    fn eval_let(&mut self, exp: ExprAst) -> ExprAst {
        fn bind_params(exp: ExprAst) -> ExprAst {
            if exp.is_empty() {
                ExprAst::Nil
            } else {
                ExprAst::Pair(PairNode::new(exp.c("aa"), bind_params(exp.cdr())))
            }
        }

        fn bind_args(exp: ExprAst) -> ExprAst {
            if exp.is_empty() {
                ExprAst::Nil
            } else {
                ExprAst::Pair(PairNode::new(exp.c("ada"), bind_args(exp.cdr())))
            }
        }

        let bindings = exp.c("da");
        bindings.print();
        let obj = ExprAst::Pair(PairNode::new(
            bind_params(bindings.clone()).make_lambda(exp.c("dd")),
            bind_args(bindings)));
        self.eval_exp(obj)
    }

    fn eval_begin(&mut self, exp: ExprAst) -> ExprAst {
        let mut _exp = exp.cdr();
        loop {
            if _exp.is_last() { break; }
            self.eval_exp(_exp.car());
            _exp = _exp.cdr();
        }
        self.eval_exp(_exp.car())
    }

    fn eval_values(&mut self, exprs: ExprAst) -> ExprAst {
        if exprs.is_empty() {
            ExprAst::Nil
        } else {
            let first = self.eval_exp(exprs.car());
            ExprAst::Pair(PairNode::new(first, self.eval_values(exprs.cdr())))
        }
    }

    fn eval_app(&mut self, expr: ExprAst) -> ExprAst {
        let _proc = self.eval_exp(expr.car());
        let _args = self.eval_values(expr.cdr());
        if _proc.is_proc() {
            let func = _proc.as_proc().func();
            return func(_args);
        } else {
            assert!(_proc.is_cproc());
            let _vars = _proc.params();
            self.env = self.env.clone().borrow_mut().extend(_vars, _args);
            let begin = ExprAst::Symbol(SymbolNode::new("begin"));
            let res = self.eval_exp(ExprAst::Pair(PairNode::new(begin, _proc.body())));
            self.env = self.env.clone().borrow_mut().parent().unwrap();
            res
        }
    }

    fn eval_lambda(&mut self, expr: ExprAst) -> ExprAst {
        ExprAst::CompProc(CompProcNode::new(expr.c("da"),  //vars
                                            expr.c("dd"),  //body
                                            self.env.clone()))
    }
}

#[test]
fn test_evaler() {
    macro_rules! test_case {
        ($test_str:expr, $expect_type:ident, $expect_val:expr) => { {
            let mut evaler = Evaler::new();
            let res = evaler.eval($test_str.to_string()).unwrap();
            if res.$expect_type() != $expect_val {
                assert!(false);
            }
        }}
    }
    test_case!("11", as_int, 11);
    test_case!("'a", as_str, "a");
    test_case!(r#""hello""#, as_str, "hello");
    test_case!("#t", as_bool, true);
    test_case!("(and #t #t)", as_bool, true);
    test_case!("(and #t #f)", as_bool, false);
    test_case!("(or #t #t)", as_bool, true);
    test_case!("(or #f #f)", as_bool, false);
    test_case!("(or #t #f)", as_bool, true);
    test_case!("(set! a 1)", as_str, "OK");
    test_case!("(integer? 1)", as_bool, true);
    test_case!("(boolean? #t)", as_bool, true);
    test_case!("(boolean? #f)", as_bool, true);
    test_case!("(integer? #t)", as_bool, false);
    test_case!("(+ 1 1)", as_int, 2);
    test_case!("(- 1 1)", as_int, 0);
    test_case!("(+ 1 1  1)", as_int, 3);
    test_case!("(+ 1 1 -1 -1)", as_int, 0);
    test_case!("(/ 2 1)", as_int, 2);
    test_case!("(* 2 2)", as_int, 4);
    test_case!("(> 2 1)", as_bool, true);
    test_case!("(> 1 2)", as_bool, false);
    test_case!("(> 1 1)", as_bool, false);
    test_case!("(- (+ 3 (* 8 5)) 1)", as_int, 42);
    test_case!("(eq? 1 1)", as_bool, true);
    test_case!("(eq? 1 2)", as_bool, false);
    test_case!("(eq? 1 #f)", as_bool, false);
    test_case!("(pair? '())", as_bool, true);
    test_case!("(> (+ 1 1) 0)", as_bool, true);
    test_case!("(if (> 1 0) 1 else 2)", as_int, 1);
    test_case!("(begin (set! a 1) a)", as_int, 1);
    test_case!("(let ((a 1)) (+ a 1))", as_int, 2);
    test_case!("(let ((a 1)) (> (+ a 1) 0))", as_bool, true);
    test_case!("(let ((a 1) (b 2)) (> a b))", as_bool, false);
    test_case!("(define (add a b) (+ a b))", as_str, "OK");
    test_case!("(cond ((eq? 1 1) 1) ((> 1 2) 2) ))", as_int, 1);
    test_case!("(begin (set! x 5) (set! x 4) (+ x 1))", as_int, 5);
    test_case!("(car '(1 2))", as_int, 1);
    test_case!("(car (cdr '(1 2)))", as_int, 2);
    test_case!("(car (cons 1 2))", as_int, 1);
    test_case!("(car (cons (pair? '(1)) pair? '()))", as_bool, true);
    test_case!("(car (cdr (cons 1 2)))", as_int, 2);
    test_case!("(car (car (cons (cons 2 3) (cons 1 2))))", as_int, 2);
    test_case!("((lambda (x) x) 1)", as_int, 1);
    test_case!("((lambda (x y) (+ x y )) 1 2)", as_int, 3);
    test_case!("(define add4 (let ((x 4)) (lambda (y) (+ x y))))", as_str, "OK");
    test_case!("(begin 1 2)", as_int, 2);
    test_case!("((lambda (x) x) 5)", as_int, 5);
    test_case!("(let ((fu (lambda (x) (+ x 1)))) (fu 1))", as_int, 2);
    test_case!("((lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1)))))
                (lambda ( x y ) ( if ( = y 0) 1 (* y (x x (- y 1))))) 5)", as_int, 5is*4*3*2);
}
<|endoftext|>


<commit_before>use ast::{Ast, AstTrait};
use token::{Token, TokenTrait, Type};
use std::cmp::Ordering;

pub struct Eval {
    ast: Ast,
    stack: Vec<(Ast, usize)>,
    evaluated: bool
}

pub trait EvalTrait {
    fn eval(&mut self);
    fn is_evaluated(&self) -> bool;
}

pub trait PrettyPrint {
    fn pretty_print(&mut self) -> String;
    fn push_whitespace(&self, pretty: &mut String);
}

impl PrettyPrint for Eval {
    fn push_whitespace(&self, pretty: &mut String) {
        for _ in 0..self.stack.len() {
            pretty.push('\t');
        }
    }

    fn pretty_print(&mut self) -> String {
        let mut pretty = String::new();
        loop {
            match self.stack.pop() {
                Some(mut current) => {
                    match current.0.get_child(0) {
                        Some(mut child) => {
                            self.stack.push(current);
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => {
                            if current.0.node_val.is_some() {
                                let tok = current.0.node_val.unwrap();
                                self.push_whitespace(&mut pretty);
                                match tok.tok_type {
                                    Type::Oparen => pretty.push(')'),
                                    Type::OpenList => pretty.push('>'),
                                    _ => pretty.push_str(&tok.get_lexed())
                                }
                            }
                            pretty.push('\n');
                        }
                    }
                },
                None => {
                    match self.ast.get_child(0) {
                        Some(mut child) => {
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => break
                    }
                }
            }
            if self.stack.is_empty() && self.ast.child_count() == 0 {
                break;
            }
        }
        pretty
    }
}

impl EvalTrait for Eval {
    fn eval(&mut self) {
        let mut scope = Scope::new_root();
        while !self.evaluated {
            scope = self.eval_node(scope); // If scope says evaluate, evaluate.
        }
    }

    fn is_evaluated(&self) -> bool {
        self.evaluated
    }
}

impl Eval {
    pub fn new(ast: Ast) -> Self {
        Eval {
            ast: ast,
            stack: Vec::new(),
            evaluated: false
        }
    }

    pub fn new_option(ast: Option<Ast>) -> Self {
        match ast {
            Some(tree) => Eval {
                ast: tree,
                stack: Vec::new(),
                evaluated: false
            },
            None => panic!()
        }
    }

    fn expand_function(&mut self, scope: &Scope) -> bool {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.is_function() {
                    true => {
                        self.inject_params(scope);
                        true
                    },
                    false => false
                }
            },
            None => false
        }
    }

    fn inject_params(&self, scope: &Scope) {

    }

    fn eval_node(&mut self, mut scope: Scope) -> Scope {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.get_child(0) {
                    Some(mut child) => {
                        self.stack.push(current);
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => {
                        match self.stack.pop() {
                            Some(mut parent) => {
                                let new_index = current.1 + 1;
                                parent.0.insert_child(current.0, current.1);
                                if parent.0.child_count() > new_index {
                                    let new_child = parent.0.get_child(new_index);
                                    self.stack.push(parent);
                                    self.stack.push((new_child.unwrap(), new_index));
                                } else {
                                    self.stack.push(parent);
                                    scope.evaluate_scope = true;
                                }
                            },
                            None => self.evaluated = true
                        }
                    }
                }
            },
            None => {
                match self.ast.get_child(0) {
                    Some(mut child) => {
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => self.evaluated = true
                }
            }
        }
        if self.stack.is_empty() && self.ast.child_count() == 0 {
            self.evaluated = true;
        }
        scope
    }
}

struct Scope {
    pub parent: Option<Box<Scope>>,
    funcs: Vec<Func>,
    in_builtin: bool,
    pub evaluate_scope: bool
}

impl Scope {
    pub fn new(parent: Scope) -> Self
    {
        Scope {
            parent: Some(Box::new(parent)),
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn new_root() -> Self {
        Scope {
            parent: None,
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn push_func(&mut self, func: Func) {
        self.funcs.push(func);
    }

    pub fn find_func(&mut self, tok: Token) -> Option<Func> {
        None
    }
}

struct Func {
    name: String,
    pub body: Ast,
    pub params: Ast
}

impl Func {
    pub fn new(name: String, body: Ast, params: Ast) -> Self {
        Func {
            name: name,
            body: body,
            params: params
        }
    }

    pub fn get_name(&self) -> &String {
        &self.name
    }
}

impl Ord for Func {
    fn cmp(&self, other: &Func) -> Ordering {
        self.name.cmp(other.get_name())
    }
}

impl PartialOrd for Func {
    fn partial_cmp(&self, other: &Func) -> Option<Ordering> {
        self.name.partial_cmp(other.get_name())
    }
}

impl Eq for Func { }

impl PartialEq for Func {
    fn eq(&self, other: &Func) -> bool {
        self.name.eq(other.get_name())
    }

    fn ne(&self, other: &Func) -> bool {
        self.name.ne(other.get_name())
    }
}
<commit_msg>This is literally the most inefficient thing in the universe. After this, I will write a combination of safe and unsafe Rust code to optomize performance<commit_after>use ast::{Ast, AstTrait};
use token::{Token, TokenTrait, Type};
use std::cmp::Ordering;

pub struct Eval {
    ast: Ast,
    stack: Vec<(Ast, usize)>,
    evaluated: bool
}

pub trait EvalTrait {
    fn eval(&mut self);
    fn is_evaluated(&self) -> bool;
}

pub trait PrettyPrint {
    fn pretty_print(&mut self) -> String;
    fn push_whitespace(&self, pretty: &mut String);
}

impl PrettyPrint for Eval {
    fn push_whitespace(&self, pretty: &mut String) {
        for _ in 0..self.stack.len() {
            pretty.push('\t');
        }
    }

    fn pretty_print(&mut self) -> String {
        let mut pretty = String::new();
        loop {
            match self.stack.pop() {
                Some(mut current) => {
                    match current.0.get_child(0) {
                        Some(mut child) => {
                            self.stack.push(current);
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => {
                            if current.0.node_val.is_some() {
                                let tok = current.0.node_val.unwrap();
                                self.push_whitespace(&mut pretty);
                                match tok.tok_type {
                                    Type::Oparen => pretty.push(')'),
                                    Type::OpenList => pretty.push('>'),
                                    _ => pretty.push_str(&tok.get_lexed())
                                }
                            }
                            pretty.push('\n');
                        }
                    }
                },
                None => {
                    match self.ast.get_child(0) {
                        Some(mut child) => {
                            if child.node_val.is_some() {
                                let tok = child.node_val.unwrap();
                                if tok.tok_type == Type::Oparen {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('(');
                                    pretty.push('\n');
                                } else if tok.tok_type == Type::OpenList {
                                    self.push_whitespace(&mut pretty);
                                    pretty.push('<');
                                    pretty.push('\n');
                                }
                                child.node_val = Some(tok);
                            }
                            self.stack.push((child, 0));
                        },
                        None => break
                    }
                }
            }
            if self.stack.is_empty() && self.ast.child_count() == 0 {
                break;
            }
        }
        pretty
    }
}

impl EvalTrait for Eval {
    fn eval(&mut self) {
        let mut scope = Scope::new_root();
        while !self.evaluated {
            scope = self.eval_node(scope); // If scope says evaluate, evaluate.
        }
    }

    fn is_evaluated(&self) -> bool {
        self.evaluated
    }
}

impl Eval {
    pub fn new(ast: Ast) -> Self {
        Eval {
            ast: ast,
            stack: Vec::new(),
            evaluated: false
        }
    }

    pub fn new_option(ast: Option<Ast>) -> Self {
        match ast {
            Some(tree) => Eval {
                ast: tree,
                stack: Vec::new(),
                evaluated: false
            },
            None => panic!()
        }
    }

    fn expand_function(&mut self, scope: &Scope) -> bool {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.is_function() {
                    true => {
                        self.inject_params(scope);
                        true
                    },
                    false => false
                }
            },
            None => false
        }
    }

    fn inject_params(&self, scope: &Scope) {

    }

    fn eval_node(&mut self, mut scope: Scope) -> Scope {
        match self.stack.pop() {
            Some(mut current) => {
                match current.0.get_child(0) {
                    Some(mut child) => {
                        self.stack.push(current);
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => {
                        match self.stack.pop() {
                            Some(mut parent) => {
                                let new_index = current.1 + 1;
                                parent.0.insert_child(current.0, current.1);
                                if parent.0.child_count() > new_index {
                                    let new_child = parent.0.get_child(new_index);
                                    self.stack.push(parent);
                                    self.stack.push((new_child.unwrap(), new_index));
                                } else {
                                    self.stack.push(parent);
                                    scope.evaluate_scope = true;
                                }
                            },
                            None => self.evaluated = true
                        }
                    }
                }
            },
            None => {
                match self.ast.get_child(0) {
                    Some(mut child) => {
                        if child.node_val.is_some() {
                            let tok = child.node_val.unwrap();
                            if tok.tok_type == Type::Func {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                                self.expand_function(&scope);
                            } else {
                                child.node_val = Some(tok);
                                self.stack.push((child, 0));
                            }
                        } else {
                            self.stack.push((child, 0));
                        }
                    },
                    None => self.evaluated = true
                }
            }
        }
        if self.stack.is_empty() && self.ast.child_count() == 0 {
            self.evaluated = true;
        }
        scope
    }
}

struct Scope {
    pub parent: Option<Box<Scope>>,
    funcs: Vec<Func>,
    in_builtin: bool,
    pub evaluate_scope: bool
}

impl Scope {
    pub fn new(parent: Scope) -> Self
    {
        Scope {
            parent: Some(Box::new(parent)),
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn new_root() -> Self {
        Scope {
            parent: None,
            funcs: Vec::new(),
            in_builtin: false,
            evaluate_scope: false
        }
    }

    pub fn insert_func(&mut self, func: Func) {
        if self.find_func(func.get_name()).is_none() {
            let loc = self.funcs.binary_search(&func);
            if loc.is_err() {
                self.funcs.insert(loc.unwrap(), func);
            }
        }
    }

    pub fn find_func(&mut self, tok_str: &String) -> Option<Func> {
        let loc = self.funcs.binary_search_by(|func| {
            tok_str.cmp(func.get_name())
        });
        match loc {
            Ok(index) => Some(self.funcs.remove(index)),
            _ => {
                match self.parent {
                    Some(ref mut parent) => parent.find_func(tok_str),
                    None => None
                }
            }
        }
    }
}

struct Func {
    name: String,
    pub body: Ast,
    pub params: Ast
}

impl Func {
    pub fn new(name: String, body: Ast, params: Ast) -> Self {
        Func {
            name: name,
            body: body,
            params: params
        }
    }

    pub fn get_name(&self) -> &String {
        &self.name
    }
}

impl Ord for Func {
    fn cmp(&self, other: &Func) -> Ordering {
        self.name.cmp(other.get_name())
    }
}

impl PartialOrd for Func {
    fn partial_cmp(&self, other: &Func) -> Option<Ordering> {
        self.name.partial_cmp(other.get_name())
    }
}

impl Eq for Func { }

impl PartialEq for Func {
    fn eq(&self, other: &Func) -> bool {
        self.name.eq(other.get_name())
    }

    fn ne(&self, other: &Func) -> bool {
        self.name.ne(other.get_name())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use parse::Env;
use var::Var;
use source::Src;

pub trait Eval {
    fn eval (&self, path: Option<&[&str]>, lookup: &str) -> Option<Var>;

    fn eval_bare (&self, lookup: &str) -> Option<Var> {
        let mut lookups: Vec<&str> = lookup.split_terminator('.').collect();
        let lookup = lookups.pop().unwrap();

        let path;
        if lookups.len() > 0 { path = Some(&lookups[..]); }
        else { path = None }

        self.eval(path, lookup)
    }
}

pub struct Evaluator<'e, 'd, D:Eval + 'd> {
    data: &'d D,
    env: &'e mut Env,
    next_node: String,
    await_node: String,
}

impl<'e, 'd, D:Eval + 'd> Iterator for Evaluator<'e, 'd, D>
    where D: Eval + 'd {

    type Item = (Vec<Var>,Option<String>); //here we only return node name as an option to advance
    fn next(&mut self) -> Option<Self::Item> {
        let nn = {
            if !self.await_node.is_empty() {
                let an = self.await_node.clone();
                self.await_node.clear();
                an
            }
            else if !self.next_node.is_empty() { self.next_node.clone() }
            else { return None }
        };

        let mut r = self.run(&nn);
        let nn = r.1.clone();
        if nn.is_none() { self.next_node.clear(); }
        else { self.next_node = nn.unwrap(); }

        if self.await_node.is_empty() { r.1 = None; } //no need to return node name

        Some(r)
    }
}

impl<'e, 'd, D:Eval> Evaluator<'e, 'd, D> {
    pub fn new (env: &'e mut Env, data: &'d D) -> Evaluator<'e, 'd, D> {
        Evaluator {
            env: env, data: data,
            next_node: "root".to_owned(),
            await_node: "".to_owned()
        }
    }
    pub fn advance (&mut self) {
        self.await_node.clear();
    }

    pub fn run (&mut self, node_name: &str)
                -> (Vec<Var>,Option<String>)
        where D: Eval + 'd
    {
        let mut r = vec!();
        let mut node = None;
        let mut if_valid = false; //track for OR

        if let Some(b) = self.env.src.get_mut(node_name) { //println!("src:{:?}",b.src);
            let mut state: HashMap<String,bool> = HashMap::new();
            state.insert("this.visited".to_owned(), b.visited);
            b.visited = true;

            let await_idx = b.await_idx;
            b.await_idx = 0;

            for (i,src) in b.src[await_idx..].iter().enumerate() {
                match src {
                    &Src::Await(ref nn) => {
                        b.await_idx = i+1;
                        node = nn.clone();
                        break
                    },
                    &Src::Or(_,_) => {
                        if !if_valid {
                            continue
                        }
                        else { if_valid = false; }
                    }
                    &Src::If(_,_,_) => { if_valid = true; }
                    _ => { if_valid = false; },
                }

                let (mut vars, node_) = src.eval(&mut state, self.data);

                // reset if if was successful
                if (vars.len() > 0) || node_.is_some() { if_valid = false; }

                for n in vars.drain(..) { r.push(n); }
                if let Some((node_,await)) = node_ {
                    if await {
                        b.await_idx = i+1;
                        self.await_node = node_name.to_owned();
                    }

                    node = Some(node_);
                    break;
                }
            }
        }

        for var in r.iter_mut() {
            let mut val = None;
            match var {
                &mut Var::String(ref mut s) => { //format string
                    let mut fs = String::new();
                    let mut started = false;

                    // NOTE: we should move this out to a SYM varkind instead
                    // (parsed earlier)
                    if s.split_terminator(' ').count() == 1 {
                        if s.chars().next().unwrap() == '`' {
                            if let Some(ref val_) = self.data.eval_bare(&s[1..]) {
                                val = Some(val_.clone());
                            }
                        }
                    }
                    else {
                        for word in s.split_terminator(' ') {
                            if started { fs.push(' '); }

                            if word.chars().next().unwrap() == '`' {
                                if let Some(ref val_) = self.data.eval_bare(&word[1..]) {
                                    fs.push_str(&val_.to_string());
                                }
                            }
                            else {
                                fs.push_str(word);
                            }

                            started = true;
                        }
                        *s = fs;
                    }
                },
                _ => {}
            }

            if let Some(val) = val {
                *var = val;
            }
        }

        return (r,node)
    }
}
<commit_msg>reset on advance<commit_after>use std::collections::HashMap;
use parse::Env;
use var::Var;
use source::Src;

pub trait Eval {
    fn eval (&self, path: Option<&[&str]>, lookup: &str) -> Option<Var>;

    fn eval_bare (&self, lookup: &str) -> Option<Var> {
        let mut lookups: Vec<&str> = lookup.split_terminator('.').collect();
        let lookup = lookups.pop().unwrap();

        let path;
        if lookups.len() > 0 { path = Some(&lookups[..]); }
        else { path = None }

        self.eval(path, lookup)
    }
}

pub struct Evaluator<'e, 'd, D:Eval + 'd> {
    data: &'d D,
    env: &'e mut Env,
    next_node: String,
    await_node: String,
}

impl<'e, 'd, D:Eval + 'd> Iterator for Evaluator<'e, 'd, D>
    where D: Eval + 'd {

    type Item = (Vec<Var>,Option<String>); //here we only return node name as an option to advance
    fn next(&mut self) -> Option<Self::Item> {
        let nn = {
            if !self.await_node.is_empty() {
                let an = self.await_node.clone();
                self.await_node.clear();
                an
            }
            else if !self.next_node.is_empty() { self.next_node.clone() }
            else { return None }
        };

        let mut r = self.run(&nn);
        let nn = r.1.clone();
        if nn.is_none() { self.next_node.clear(); }
        else { self.next_node = nn.unwrap(); }

        if self.await_node.is_empty() { r.1 = None; } //no need to return node name

        Some(r)
    }
}

impl<'e, 'd, D:Eval> Evaluator<'e, 'd, D> {
    pub fn new (env: &'e mut Env, data: &'d D) -> Evaluator<'e, 'd, D> {
        Evaluator {
            env: env, data: data,
            next_node: "root".to_owned(),
            await_node: "".to_owned()
        }
    }
    pub fn advance (&mut self) {
        if let Some(b) = self.env.src.get_mut(&self.await_node) {
            b.await_idx = 0; //reset on advance
        }

        self.await_node.clear();
    }

    pub fn run (&mut self, node_name: &str)
                -> (Vec<Var>,Option<String>)
        where D: Eval + 'd
    {
        let mut r = vec!();
        let mut node = None;
        let mut if_valid = false; //track for OR

        if let Some(b) = self.env.src.get_mut(node_name) { //println!("src:{:?}",b.src);
            let mut state: HashMap<String,bool> = HashMap::new();
            state.insert("this.visited".to_owned(), b.visited);
            b.visited = true;

            let await_idx = b.await_idx;
            b.await_idx = 0;

            for (i,src) in b.src[await_idx..].iter().enumerate() {
                match src {
                    &Src::Await(ref nn) => {
                        b.await_idx = i+1;
                        node = nn.clone();
                        break
                    },
                    &Src::Or(_,_) => {
                        if !if_valid {
                            continue
                        }
                        else { if_valid = false; }
                    }
                    &Src::If(_,_,_) => { if_valid = true; }
                    _ => { if_valid = false; },
                }

                let (mut vars, node_) = src.eval(&mut state, self.data);

                // reset if if was successful
                if (vars.len() > 0) || node_.is_some() { if_valid = false; }

                for n in vars.drain(..) { r.push(n); }
                if let Some((node_,await)) = node_ {
                    if await {
                        b.await_idx = i+1;
                        self.await_node = node_name.to_owned();
                    }

                    node = Some(node_);
                    break;
                }
            }
        }

        for var in r.iter_mut() {
            let mut val = None;
            match var {
                &mut Var::String(ref mut s) => { //format string
                    let mut fs = String::new();
                    let mut started = false;

                    // NOTE: we should move this out to a SYM varkind instead
                    // (parsed earlier)
                    if s.split_terminator(' ').count() == 1 {
                        if s.chars().next().unwrap() == '`' {
                            if let Some(ref val_) = self.data.eval_bare(&s[1..]) {
                                val = Some(val_.clone());
                            }
                        }
                    }
                    else {
                        for word in s.split_terminator(' ') {
                            if started { fs.push(' '); }

                            if word.chars().next().unwrap() == '`' {
                                if let Some(ref val_) = self.data.eval_bare(&word[1..]) {
                                    fs.push_str(&val_.to_string());
                                }
                            }
                            else {
                                fs.push_str(word);
                            }

                            started = true;
                        }
                        *s = fs;
                    }
                },
                _ => {}
            }

            if let Some(val) = val {
                *var = val;
            }
        }

        return (r,node)
    }
}
<|endoftext|>