<commit_before>//! Various utility function with a specific architecture implementation

pub unsafe fn atomic_set_bit<T>(nr: usize, addr: *mut T) {
    asm!("lock bts $1, $0"
         : "=*m" (addr as *mut u32)
         : "Ir" (nr)
         : "memory"
         : "volatile");
}

pub unsafe fn atomic_clear_bit<T>(nr: usize, addr: *mut T) {
    asm!("lock btr $1, $0"
         : "=*m" (addr as *mut u32)
         : "Ir" (nr)
         : "memory"
         : "volatile");
}

pub fn first_bit(data: usize) -> usize {
    unsafe {
        let ret;

        asm!("bsf $1, $0\n\t\
              jnz 1f\n\t
              mov $$0, $0\n\t
              1:\n\t"
             : "=r" (ret)
             : "r" (data)
             :: "volatile");

        ret
    }
}

pub fn wmb() {
    unsafe {
        asm!("sfence" ::: "memory" : "volatile");
    }
}

#[test]
pub fn test_set_and_clear() {
    let mut array = [0u32; 4];

    unsafe {
        atomic_set_bit(1, &mut array[0] as *mut u32);
        atomic_set_bit(2, &mut array[0] as *mut u32);
        atomic_set_bit(3, &mut array[0] as *mut u32);
        atomic_set_bit(32, &mut array[0] as *mut u32);
        atomic_set_bit(33, &mut array[0] as *mut u32);
        atomic_set_bit(34, &mut array[0] as *mut u32);
        atomic_set_bit(127, &mut array[0] as *mut u32);

        assert_eq!(array[0], 0xE);
        assert_eq!(array[1], 0x7);
        assert_eq!(array[2], 0x0);
        assert_eq!(array[3], 0x80000000);

        atomic_clear_bit(1, &mut array[0] as *mut u32);
        atomic_clear_bit(2, &mut array[0] as *mut u32);
        atomic_clear_bit(3, &mut array[0] as *mut u32);
        atomic_clear_bit(32, &mut array[0] as *mut u32);
        atomic_clear_bit(33, &mut array[0] as *mut u32);
        atomic_clear_bit(34, &mut array[0] as *mut u32);
        atomic_clear_bit(127, &mut array[0] as *mut u32);

        assert_eq!(array[0], 0x0);
        assert_eq!(array[1], 0x0);
        assert_eq!(array[2], 0x0);
        assert_eq!(array[3], 0x0);
    }
}

#[test]
pub fn test_first_bit() {
    assert_eq!(first_bit(0x0), 0);
    assert_eq!(first_bit(0x1), 0);
    assert_eq!(first_bit(0x2), 1);
    assert_eq!(first_bit(0x3), 0);
    assert_eq!(first_bit(0x8000), 15);
    assert_eq!(first_bit(0xFF80), 7);
    assert_eq!(first_bit(0x80000000), 31);
}
<commit_msg>x86/utils: Add mb() and rmb()<commit_after>//! Various utility function with a specific architecture implementation

pub unsafe fn atomic_set_bit<T>(nr: usize, addr: *mut T) {
    asm!("lock bts $1, $0"
         : "=*m" (addr as *mut u32)
         : "Ir" (nr)
         : "memory"
         : "volatile");
}

pub unsafe fn atomic_clear_bit<T>(nr: usize, addr: *mut T) {
    asm!("lock btr $1, $0"
         : "=*m" (addr as *mut u32)
         : "Ir" (nr)
         : "memory"
         : "volatile");
}

pub fn first_bit(data: usize) -> usize {
    unsafe {
        let ret;

        asm!("bsf $1, $0\n\t\
              jnz 1f\n\t
              mov $$0, $0\n\t
              1:\n\t"
             : "=r" (ret)
             : "r" (data)
             :: "volatile");

        ret
    }
}

/// Memory barrier
pub fn mb() {
    unsafe {
        asm!("mfence" ::: "memory" : "volatile");
    }
}

/// Read memory barrier
pub fn rmb() {
    unsafe {
        asm!("lfence" ::: "memory" : "volatile");
    }
}

/// Write memory barrier
pub fn wmb() {
    unsafe {
        asm!("sfence" ::: "memory" : "volatile");
    }
}

#[test]
pub fn test_set_and_clear() {
    let mut array = [0u32; 4];

    unsafe {
        atomic_set_bit(1, &mut array[0] as *mut u32);
        atomic_set_bit(2, &mut array[0] as *mut u32);
        atomic_set_bit(3, &mut array[0] as *mut u32);
        atomic_set_bit(32, &mut array[0] as *mut u32);
        atomic_set_bit(33, &mut array[0] as *mut u32);
        atomic_set_bit(34, &mut array[0] as *mut u32);
        atomic_set_bit(127, &mut array[0] as *mut u32);

        assert_eq!(array[0], 0xE);
        assert_eq!(array[1], 0x7);
        assert_eq!(array[2], 0x0);
        assert_eq!(array[3], 0x80000000);

        atomic_clear_bit(1, &mut array[0] as *mut u32);
        atomic_clear_bit(2, &mut array[0] as *mut u32);
        atomic_clear_bit(3, &mut array[0] as *mut u32);
        atomic_clear_bit(32, &mut array[0] as *mut u32);
        atomic_clear_bit(33, &mut array[0] as *mut u32);
        atomic_clear_bit(34, &mut array[0] as *mut u32);
        atomic_clear_bit(127, &mut array[0] as *mut u32);

        assert_eq!(array[0], 0x0);
        assert_eq!(array[1], 0x0);
        assert_eq!(array[2], 0x0);
        assert_eq!(array[3], 0x0);
    }
}

#[test]
pub fn test_first_bit() {
    assert_eq!(first_bit(0x0), 0);
    assert_eq!(first_bit(0x1), 0);
    assert_eq!(first_bit(0x2), 1);
    assert_eq!(first_bit(0x3), 0);
    assert_eq!(first_bit(0x8000), 15);
    assert_eq!(first_bit(0xFF80), 7);
    assert_eq!(first_bit(0x80000000), 31);
}
<|endoftext|>


<commit_before>// Copyright 2012-2016 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.

// Basic test for liveness constraints: the region (`R1`) that appears
// in the type of `p` includes the points after `&v[0]` up to (but not
// including) the call to `use_x`. The `else` branch is not included.

// ignore-tidy-linelength
// compile-flags:-Znll -Zverbose
//                     ^^^^^^^^^ force compiler to dump more region information

#![allow(warnings)]

fn use_x(_: usize) -> bool { true }

fn main() {
    let mut v = [1, 2, 3];
    let p: Wrap<& /* R1 */ usize> = Wrap { value: &v[0] };
    if true {
        use_x(*p.value);
    } else {
        use_x(22);
    }

    // `p` will get dropped here. Because the `#[may_dangle]`
    // attribute is not present on `Wrap`, we must conservatively
    // assume that the dtor may access the `value` field, and hence we
    // must consider R1 to be live.
}

struct Wrap<T> {
    value: T
}

// Look ma, no `#[may_dangle]` attribute here.
impl<T> Drop for Wrap<T> {
    fn drop(&mut self) { }
}

// END RUST SOURCE
// START rustc.main.nll.0.mir
// | '_#5r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1], bb2[2], bb3[0], bb4[0], bb4[1], bb4[2], bb6[0], bb7[0], bb7[1], bb8[0]}
// END rustc.main.nll.0.mir
<commit_msg>Disable region-liveness-drop-no-may-dangle.rs<commit_after>// Copyright 2012-2016 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.

// Basic test for liveness constraints: the region (`R1`) that appears
// in the type of `p` includes the points after `&v[0]` up to (but not
// including) the call to `use_x`. The `else` branch is not included.

// ignore-tidy-linelength
// ignore-test #46267
// compile-flags:-Znll -Zverbose
//                     ^^^^^^^^^ force compiler to dump more region information

#![allow(warnings)]

fn use_x(_: usize) -> bool { true }

fn main() {
    let mut v = [1, 2, 3];
    let p: Wrap<& /* R1 */ usize> = Wrap { value: &v[0] };
    if true {
        use_x(*p.value);
    } else {
        use_x(22);
    }

    // `p` will get dropped here. Because the `#[may_dangle]`
    // attribute is not present on `Wrap`, we must conservatively
    // assume that the dtor may access the `value` field, and hence we
    // must consider R1 to be live.
}

struct Wrap<T> {
    value: T
}

// Look ma, no `#[may_dangle]` attribute here.
impl<T> Drop for Wrap<T> {
    fn drop(&mut self) { }
}

// END RUST SOURCE
// START rustc.main.nll.0.mir
// | '_#5r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1], bb2[2], bb3[0], bb4[0], bb4[1], bb4[2], bb6[0], bb7[0], bb7[1], bb8[0]}
// END rustc.main.nll.0.mir
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use std::mem;
use libc::c_int;
use num::complex::{
    Complex32,
    Complex64,
};
use error::Error;
use ll::*;
use matrix::{
    Matrix,
};
use scalar::Scalar;
use types::{Order, Transpose};
use util::transpose_data;

pub trait Gels: Sized {
    fn gels(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error> {
        //TODO: nancheck

        let work_len = try!(Gels::gels_work_len(a_trans, a, b));
        let mut work: Vec<_> = Vec::with_capacity(work_len as usize);
        unsafe {
            work.set_len(work_len as usize);
        }

        Gels::gels_work(layout, a_trans, a, b, &mut work[..])
    }

    fn gels_work(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error>;
    fn gels_work_len(a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error>;
}

macro_rules! least_sq_impl(($($t: ident), +) => ($(
    impl Gels for $t {
        fn gels_work(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error> {
            let mut info: c_int = 0;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();

            match layout {
                Order::ColMajor => unsafe {
                    let lda = m;
                    let ldb = b.rows();

                    prefix!($t, gels_)(
                        a_trans.as_i8().as_mut(),
                        m.as_mut(), n.as_mut(),
                        nrhs.as_mut(),
                        a.as_mut_ptr(), lda.as_mut(),
                        b.as_mut_ptr(), ldb.as_mut(),
                        work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                        &mut info as *mut c_int);
                },
                Order::RowMajor => {
                    let lda = n;
                    let ldb = nrhs;
                    let mrhs = cmp::max(m, n);

                    let lda_t = cmp::max(1, m);
                    let ldb_t = cmp::max(1, mrhs);

                    let a_t_len = (lda_t * cmp::max(1, n)) as usize;
                    let b_t_len = (ldb_t * cmp::max(1, nrhs)) as usize;
                    let mut a_t = Vec::with_capacity(a_t_len);
                    let mut b_t = Vec::with_capacity(b_t_len);

                    unsafe {
                        a_t.set_len(a_t_len);
                        b_t.set_len(b_t_len);

                        transpose_data(Order::RowMajor, m as isize, n as isize, a.as_ptr(), lda as isize, a_t.as_mut_ptr(), lda_t as isize);
                        transpose_data(Order::RowMajor, mrhs as isize, nrhs as isize, b.as_ptr(), ldb as isize, b_t.as_mut_ptr(), ldb_t as isize);

                        prefix!($t, gels_)(
                            a_trans.as_i8().as_mut(),
                            m.as_mut(), n.as_mut(),
                            nrhs.as_mut(),
                            a_t.as_mut_ptr(), lda_t.as_mut(),
                            b_t.as_mut_ptr(), ldb_t.as_mut(),
                            work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                            &mut info as *mut c_int);

                        transpose_data(Order::ColMajor, m as isize, n as isize, a_t.as_ptr(), lda_t as isize, a.as_mut_ptr(), lda as isize);
                        transpose_data(Order::ColMajor, mrhs as isize, nrhs as isize, b_t.as_ptr(), ldb_t as isize, b.as_mut_ptr(), ldb as isize);
                    }
                }
            }

            match info {
                0 => Ok(()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }

        fn gels_work_len(a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error> {
            let mut info: c_int = 0;
            let mut len_info: $t = unsafe { mem::zeroed() };
            let len_ptr = (&mut len_info) as *mut $t;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();
            let lda_t = cmp::max(1, m);
            let ldb_t = cmp::max(1, cmp::max(m, n));

            unsafe {
                prefix!($t, gels_)(
                    a_trans.as_i8().as_mut(),
                    m.as_mut(), n.as_mut(),
                    nrhs.as_mut(),
                    a.as_mut_ptr(), lda_t.as_mut(),
                    b.as_mut_ptr(), ldb_t.as_mut(),
                    len_ptr, (-1 as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(len_info.as_work()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }
    }
)+));

least_sq_impl!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod gesv_tests {
    use types::Order::*;
    use types::Transpose;
    use matrix::tests::M;
    use least_squares::Gels;

    #[test]
    fn col_major() {
        let mut a = M(3i32, 2i32, vec![2.0f32,4.0,7.0,3.0,9.0,4.0]);
        let mut b = M(3i32, 2i32, vec![2.0f32,4.0,7.0,6.0,18.0,8.0]);

        Gels::gels(ColMajor, &Transpose::None, &mut a, &mut b).unwrap();

        let M(_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 0.0, 2.0, 0.0]);
    }

    #[test]
    fn row_major() {
        let mut a = M(3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);
        let mut b = M(3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);

        Gels::gels(RowMajor, &Transpose::None, &mut a, &mut b).unwrap();

        let M(_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
    }
}
<commit_msg>Name tests mod correctly<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use std::mem;
use libc::c_int;
use num::complex::{
    Complex32,
    Complex64,
};
use error::Error;
use ll::*;
use matrix::{
    Matrix,
};
use scalar::Scalar;
use types::{Order, Transpose};
use util::transpose_data;

pub trait Gels: Sized {
    fn gels(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error> {
        //TODO: nancheck

        let work_len = try!(Gels::gels_work_len(a_trans, a, b));
        let mut work: Vec<_> = Vec::with_capacity(work_len as usize);
        unsafe {
            work.set_len(work_len as usize);
        }

        Gels::gels_work(layout, a_trans, a, b, &mut work[..])
    }

    fn gels_work(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error>;
    fn gels_work_len(a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error>;
}

macro_rules! least_sq_impl(($($t: ident), +) => ($(
    impl Gels for $t {
        fn gels_work(layout: Order, a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error> {
            let mut info: c_int = 0;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();

            match layout {
                Order::ColMajor => unsafe {
                    let lda = m;
                    let ldb = b.rows();

                    prefix!($t, gels_)(
                        a_trans.as_i8().as_mut(),
                        m.as_mut(), n.as_mut(),
                        nrhs.as_mut(),
                        a.as_mut_ptr(), lda.as_mut(),
                        b.as_mut_ptr(), ldb.as_mut(),
                        work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                        &mut info as *mut c_int);
                },
                Order::RowMajor => {
                    let lda = n;
                    let ldb = nrhs;
                    let mrhs = cmp::max(m, n);

                    let lda_t = cmp::max(1, m);
                    let ldb_t = cmp::max(1, mrhs);

                    let a_t_len = (lda_t * cmp::max(1, n)) as usize;
                    let b_t_len = (ldb_t * cmp::max(1, nrhs)) as usize;
                    let mut a_t = Vec::with_capacity(a_t_len);
                    let mut b_t = Vec::with_capacity(b_t_len);

                    unsafe {
                        a_t.set_len(a_t_len);
                        b_t.set_len(b_t_len);

                        transpose_data(Order::RowMajor, m as isize, n as isize, a.as_ptr(), lda as isize, a_t.as_mut_ptr(), lda_t as isize);
                        transpose_data(Order::RowMajor, mrhs as isize, nrhs as isize, b.as_ptr(), ldb as isize, b_t.as_mut_ptr(), ldb_t as isize);

                        prefix!($t, gels_)(
                            a_trans.as_i8().as_mut(),
                            m.as_mut(), n.as_mut(),
                            nrhs.as_mut(),
                            a_t.as_mut_ptr(), lda_t.as_mut(),
                            b_t.as_mut_ptr(), ldb_t.as_mut(),
                            work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                            &mut info as *mut c_int);

                        transpose_data(Order::ColMajor, m as isize, n as isize, a_t.as_ptr(), lda_t as isize, a.as_mut_ptr(), lda as isize);
                        transpose_data(Order::ColMajor, mrhs as isize, nrhs as isize, b_t.as_ptr(), ldb_t as isize, b.as_mut_ptr(), ldb as isize);
                    }
                }
            }

            match info {
                0 => Ok(()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }

        fn gels_work_len(a_trans: &Transpose, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error> {
            let mut info: c_int = 0;
            let mut len_info: $t = unsafe { mem::zeroed() };
            let len_ptr = (&mut len_info) as *mut $t;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();
            let lda_t = cmp::max(1, m);
            let ldb_t = cmp::max(1, cmp::max(m, n));

            unsafe {
                prefix!($t, gels_)(
                    a_trans.as_i8().as_mut(),
                    m.as_mut(), n.as_mut(),
                    nrhs.as_mut(),
                    a.as_mut_ptr(), lda_t.as_mut(),
                    b.as_mut_ptr(), ldb_t.as_mut(),
                    len_ptr, (-1 as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(len_info.as_work()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }
    }
)+));

least_sq_impl!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod gels_tests {
    use types::Order::*;
    use types::Transpose;
    use matrix::tests::M;
    use least_squares::Gels;

    #[test]
    fn col_major() {
        let mut a = M(3i32, 2i32, vec![2.0f32,4.0,7.0,3.0,9.0,4.0]);
        let mut b = M(3i32, 2i32, vec![2.0f32,4.0,7.0,6.0,18.0,8.0]);

        Gels::gels(ColMajor, &Transpose::None, &mut a, &mut b).unwrap();

        let M(_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 0.0, 2.0, 0.0]);
    }

    #[test]
    fn row_major() {
        let mut a = M(3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);
        let mut b = M(3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);

        Gels::gels(RowMajor, &Transpose::None, &mut a, &mut b).unwrap();

        let M(_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashSet};

use reqwest::Url;
use serde::Deserialize;
use serde_json::Value;

/// A Rosetta Code task.
#[derive(Clone, PartialEq, Eq, Hash, Debug, Deserialize)]
pub struct Task {
    /// The ID of the page containing the task in the MediaWiki API.
    #[serde(rename = "pageid")]
    pub id: u64,

    /// The human-readable title of the task.
    pub title: String,
}

/// Encapsulates errors that might occur during JSON parsing.
#[derive(Debug)]
enum TaskParseError {
    /// Something went wrong with the HTTP request to the API.
    Http(reqwest::Error),

    /// Could not parse a URL
    Url(reqwest::UrlError),

    /// There was a problem parsing the API response into JSON.
    Json(serde_json::Error),

    /// The response JSON contained unexpected keys or values.
    UnexpectedFormat,
}

impl From<serde_json::Error> for TaskParseError {
    fn from(err: serde_json::Error) -> Self {
        TaskParseError::Json(err)
    }
}

impl From<reqwest::UrlError> for TaskParseError {
    fn from(err: reqwest::UrlError) -> Self {
        TaskParseError::Url(err)
    }
}

impl From<reqwest::Error> for TaskParseError {
    fn from(err: reqwest::Error) -> Self {
        TaskParseError::Http(err)
    }
}

/// Represents a category of pages on Rosetta Code, such as "Rust".
struct Category {
    name: String,
    continue_params: Option<BTreeMap<String, String>>,
}

impl Category {
    fn new(name: &str) -> Category {
        let mut continue_params = BTreeMap::new();
        continue_params.insert("continue".to_owned(), "".to_owned());

        Category {
            name: name.to_owned(),
            continue_params: Some(continue_params),
        }
    }
}

/// Sends a request to Rosetta Code through the MediaWiki API. If successful, returns the response
/// as a JSON object.
fn query_api(
    category_name: &str,
    continue_params: &BTreeMap<String, String>,
) -> Result<Value, TaskParseError> {
    let mut url = Url::parse("http://rosettacode.org/mw/api.php")?;
    url.query_pairs_mut()
        .append_pair("action", "query")
        .append_pair("list", "categorymembers")
        .append_pair("cmtitle", &format!("Category:{}", category_name))
        .append_pair("cmlimit", "500")
        .append_pair("format", "json")
        .extend_pairs(continue_params);

    Ok(reqwest::get(url)?.json()?)
}

/// Given a JSON object, parses the task information from the MediaWiki API response.
fn parse_tasks(json: &Value) -> Result<Vec<Task>, TaskParseError> {
    let tasks_json = json
        .pointer("/query/categorymembers")
        .and_then(Value::as_array)
        .ok_or(TaskParseError::UnexpectedFormat)?;

    tasks_json
        .iter()
        .map(|json| Task::deserialize(json).map_err(From::from))
        .collect()
}

impl Iterator for Category {
    type Item = Vec<Task>;

    fn next(&mut self) -> Option<Self::Item> {
        self.continue_params.as_ref()?;

        query_api(&self.name, self.continue_params.as_ref().unwrap())
            .and_then(|result| {
                // If there are more pages of results to request, save them for the next iteration.
                self.continue_params =
                    result
                        .get("continue")
                        .and_then(Value::as_object)
                        .map(|continue_params| {
                            continue_params
                                .iter()
                                .map(|(key, value)| {
                                    (key.to_owned(), value.as_str().unwrap().to_owned())
                                })
                                .collect()
                        });

                parse_tasks(&result)
            })
            .map_err(|err| println!("Error parsing response: {:?}", err))
            .ok()
    }
}

pub fn all_tasks() -> Vec<Task> {
    Category::new("Programming Tasks").flatten().collect()
}

pub fn unimplemented_tasks(lang: &str) -> Vec<Task> {
    let all_tasks = all_tasks().iter().cloned().collect::<HashSet<_>>();
    let implemented_tasks = Category::new(lang).flatten().collect::<HashSet<_>>();
    let mut unimplemented_tasks = all_tasks
        .difference(&implemented_tasks)
        .cloned()
        .collect::<Vec<Task>>();
    unimplemented_tasks.sort_by(|a, b| a.title.cmp(&b.title));
    unimplemented_tasks
}
<commit_msg>use ? operator as well<commit_after>use std::collections::{BTreeMap, HashSet};

use reqwest::Url;
use serde::Deserialize;
use serde_json::Value;

/// A Rosetta Code task.
#[derive(Clone, PartialEq, Eq, Hash, Debug, Deserialize)]
pub struct Task {
    /// The ID of the page containing the task in the MediaWiki API.
    #[serde(rename = "pageid")]
    pub id: u64,

    /// The human-readable title of the task.
    pub title: String,
}

/// Encapsulates errors that might occur during JSON parsing.
#[derive(Debug)]
enum TaskParseError {
    /// Something went wrong with the HTTP request to the API.
    Http(reqwest::Error),

    /// Could not parse a URL
    Url(reqwest::UrlError),

    /// There was a problem parsing the API response into JSON.
    Json(serde_json::Error),

    /// The response JSON contained unexpected keys or values.
    UnexpectedFormat,
}

impl From<serde_json::Error> for TaskParseError {
    fn from(err: serde_json::Error) -> Self {
        TaskParseError::Json(err)
    }
}

impl From<reqwest::UrlError> for TaskParseError {
    fn from(err: reqwest::UrlError) -> Self {
        TaskParseError::Url(err)
    }
}

impl From<reqwest::Error> for TaskParseError {
    fn from(err: reqwest::Error) -> Self {
        TaskParseError::Http(err)
    }
}

/// Represents a category of pages on Rosetta Code, such as "Rust".
struct Category {
    name: String,
    continue_params: Option<BTreeMap<String, String>>,
}

impl Category {
    fn new(name: &str) -> Category {
        let mut continue_params = BTreeMap::new();
        continue_params.insert("continue".to_owned(), "".to_owned());

        Category {
            name: name.to_owned(),
            continue_params: Some(continue_params),
        }
    }
}

/// Sends a request to Rosetta Code through the MediaWiki API. If successful, returns the response
/// as a JSON object.
fn query_api(
    category_name: &str,
    continue_params: &BTreeMap<String, String>,
) -> Result<Value, TaskParseError> {
    let mut url = Url::parse("http://rosettacode.org/mw/api.php")?;
    url.query_pairs_mut()
        .append_pair("action", "query")
        .append_pair("list", "categorymembers")
        .append_pair("cmtitle", &format!("Category:{}", category_name))
        .append_pair("cmlimit", "500")
        .append_pair("format", "json")
        .extend_pairs(continue_params);

    Ok(reqwest::get(url)?.json()?)
}

/// Given a JSON object, parses the task information from the MediaWiki API response.
fn parse_tasks(json: &Value) -> Result<Vec<Task>, TaskParseError> {
    let tasks_json = json
        .pointer("/query/categorymembers")
        .and_then(Value::as_array)
        .ok_or(TaskParseError::UnexpectedFormat)?;

    tasks_json
        .iter()
        .map(|json| Task::deserialize(json).map_err(From::from))
        .collect()
}

impl Iterator for Category {
    type Item = Vec<Task>;

    fn next(&mut self) -> Option<Self::Item> {
        self.continue_params.as_ref()?;

        query_api(&self.name, self.continue_params.as_ref()?)
            .and_then(|result| {
                // If there are more pages of results to request, save them for the next iteration.
                self.continue_params =
                    result
                        .get("continue")
                        .and_then(Value::as_object)
                        .map(|continue_params| {
                            continue_params
                                .iter()
                                .map(|(key, value)| {
                                    (key.to_owned(), value.as_str().unwrap().to_owned())
                                })
                                .collect()
                        });

                parse_tasks(&result)
            })
            .map_err(|err| println!("Error parsing response: {:?}", err))
            .ok()
    }
}

pub fn all_tasks() -> Vec<Task> {
    Category::new("Programming Tasks").flatten().collect()
}

pub fn unimplemented_tasks(lang: &str) -> Vec<Task> {
    let all_tasks = all_tasks().iter().cloned().collect::<HashSet<_>>();
    let implemented_tasks = Category::new(lang).flatten().collect::<HashSet<_>>();
    let mut unimplemented_tasks = all_tasks
        .difference(&implemented_tasks)
        .cloned()
        .collect::<Vec<Task>>();
    unimplemented_tasks.sort_by(|a, b| a.title.cmp(&b.title));
    unimplemented_tasks
}
<|endoftext|>


<commit_before>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// External Dependencies ------------------------------------------------------
use chrono;
use rayon::iter::{ParallelIterator, IntoParallelIterator};

// Discord Dependencies -------------------------------------------------------
use discord::model::{ChannelId, ServerId};

// Internal Dependencies ------------------------------------------------------
use ::bot::{Bot, BotConfig};
use ::core::EventQueue;
use ::action::{ActionHandler, ActionGroup, MessageActions};
use ::db::models::Streamer;

// Stream Online Check Implementation -----------------------------------------
pub struct Action {
    server_id: ServerId
}

impl Action {
    pub fn new(server_id: ServerId) -> Box<Action> {
        Box::new(Action {
            server_id: server_id
        })
    }
}

impl ActionHandler for Action {

    fn run(&mut self, bot: &mut Bot, config: &BotConfig, _: &mut EventQueue) -> ActionGroup {
        if let Some(server) = bot.get_server(&self.server_id) {

            // Run HTTP requests in parallel
            let states: Vec<(Streamer, Option<bool>, ActionGroup)> = server.list_streamers().into_par_iter().map(|streamer| {
                check_stream(config, streamer)

            }).collect();

            // Then check results in the bot thread
            states.into_iter().flat_map(|(streamer, state, actions)| {

                // Update last known streaming state in database
                if let Some(state) = state {
                    server.update_streamer_online_state(
                        &streamer.twitch_nick,
                        state
                    );
                }

                actions

            }).collect()

        } else {
            vec![]
        }
    }

}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[OnlineCheckAction]")
    }
}

fn check_stream(config: &BotConfig, streamer: Streamer) -> (Streamer, Option<bool>, ActionGroup) {
    match super::stream::get_stream(config, &streamer.twitch_nick) {
        Ok(stream) => {

            let is_online = stream.stream_type == "live";
            if is_online != streamer.is_online {

                let channel_id: u64 = streamer.channel_id.parse().expect("Invalid channel id!");
                let channel_id = ChannelId(channel_id);

                if is_online {
                    info!(
                        "[Twitch] \"{}\" is now online, playing \"{}\" in {}p for {} viewers.",
                        streamer.twitch_nick,
                        stream.game,
                        stream.resolution,
                        stream.viewers
                    );

                    // Wait at least 60 seconds between every online announcement
                    let now = chrono::UTC::now().timestamp() as i32;
                    let actions: ActionGroup = if now > streamer.last_online + 60 {
                        vec![
                            MessageActions::Send::single_public_channel(&channel_id, format!(
                                "Twitch streamer **{}** is now online, playing **{}** in {}p for {} viewers!",
                                streamer.twitch_nick,
                                stream.game,
                                stream.resolution,
                                stream.viewers
                            )),
                            MessageActions::Send::single_public_channel(&channel_id, format!(
                                "https://twitch.tv/{}",
                                streamer.twitch_nick,
                            ))
                        ]

                    } else {
                        vec![]
                    };
                    (streamer, Some(true), actions)

                } else {
                    info!( "[Twitch] \"{}\" is now offline.", streamer.twitch_nick);
                    (streamer, Some(false), vec![])
                }

            } else {
                info!("[Twitch] No state change for \"{}\"", streamer.twitch_nick);
                (streamer, None, vec![])
            }

        },
        Err(_) => {
            warn!(
                "[Twitch] Failed to query twitch API for \"{}\".",
                streamer.twitch_nick
            );
            (streamer, None, vec![])
        }
    }
}

<commit_msg>Alert current channel when a twitch streamer goes online.<commit_after>// STD Dependencies -----------------------------------------------------------
use std::fmt;

// External Dependencies ------------------------------------------------------
use chrono;
use rayon::iter::{ParallelIterator, IntoParallelIterator};

// Discord Dependencies -------------------------------------------------------
use discord::model::{ChannelId, ServerId};

// Internal Dependencies ------------------------------------------------------
use ::bot::{Bot, BotConfig};
use ::core::EventQueue;
use ::action::{ActionHandler, ActionGroup, MessageActions};
use ::db::models::Streamer;

// Stream Online Check Implementation -----------------------------------------
pub struct Action {
    server_id: ServerId
}

impl Action {
    pub fn new(server_id: ServerId) -> Box<Action> {
        Box::new(Action {
            server_id: server_id
        })
    }
}

impl ActionHandler for Action {

    fn run(&mut self, bot: &mut Bot, config: &BotConfig, _: &mut EventQueue) -> ActionGroup {
        if let Some(server) = bot.get_server(&self.server_id) {

            // Run HTTP requests in parallel
            let states: Vec<(Streamer, Option<bool>, ActionGroup)> = server.list_streamers().into_par_iter().map(|streamer| {
                check_stream(config, streamer)

            }).collect();

            // Then check results in the bot thread
            states.into_iter().flat_map(|(streamer, state, actions)| {

                // Update last known streaming state in database
                if let Some(state) = state {
                    server.update_streamer_online_state(
                        &streamer.twitch_nick,
                        state
                    );
                }

                actions

            }).collect()

        } else {
            vec![]
        }
    }

}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[OnlineCheckAction]")
    }
}

fn check_stream(config: &BotConfig, streamer: Streamer) -> (Streamer, Option<bool>, ActionGroup) {
    match super::stream::get_stream(config, &streamer.twitch_nick) {
        Ok(stream) => {

            let is_online = stream.stream_type == "live";
            if is_online != streamer.is_online {

                let channel_id: u64 = streamer.channel_id.parse().expect("Invalid channel id!");
                let channel_id = ChannelId(channel_id);

                if is_online {
                    info!(
                        "[Twitch] \"{}\" is now online, playing \"{}\" in {}p for {} viewers.",
                        streamer.twitch_nick,
                        stream.game,
                        stream.resolution,
                        stream.viewers
                    );

                    // Wait at least 60 seconds between every online announcement
                    let now = chrono::UTC::now().timestamp() as i32;
                    let actions: ActionGroup = if now > streamer.last_online + 60 {
                        vec![
                            MessageActions::Send::single_public_channel(&channel_id, format!(
                                "@here Twitch streamer **{}** is now online, playing **{}** in {}p for {} viewers!",
                                streamer.twitch_nick,
                                stream.game,
                                stream.resolution,
                                stream.viewers
                            )),
                            MessageActions::Send::single_public_channel(&channel_id, format!(
                                "https://twitch.tv/{}",
                                streamer.twitch_nick,
                            ))
                        ]

                    } else {
                        vec![]
                    };
                    (streamer, Some(true), actions)

                } else {
                    info!( "[Twitch] \"{}\" is now offline.", streamer.twitch_nick);
                    (streamer, Some(false), vec![])
                }

            } else {
                info!("[Twitch] No state change for \"{}\"", streamer.twitch_nick);
                (streamer, None, vec![])
            }

        },
        Err(_) => {
            warn!(
                "[Twitch] Failed to query twitch API for \"{}\".",
                streamer.twitch_nick
            );
            (streamer, None, vec![])
        }
    }
}

<|endoftext|>


<commit_before>//! The `evaluate_expressions` module...

use backend::zcode::zfile::{ZOP, Operand, Variable, Constant, LargeConstant, Zfile};
use frontend::ast::{ASTNode};
use frontend::codegen;
use frontend::codegen::{CodeGenManager};
use frontend::lexer::Token::{TokNumOp, TokCompOp, TokLogOp, TokInt, TokBoolean, TokVariable, TokFunction, TokString};

pub fn evaluate_expression<'a>(node: &'a ASTNode, code: &mut Vec<ZOP>, mut manager: &mut CodeGenManager<'a>, mut out: &mut Zfile) -> Operand {
    let mut temp_ids = CodeGenManager::new_temp_var_vec();
    evaluate_expression_internal(node, code, &mut temp_ids, manager, &mut out)
}

/// Evaluates an expression node to zCode.
fn evaluate_expression_internal<'a>(node: &'a ASTNode, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>, mut out: &mut Zfile) -> Operand {
    let n = node.as_default();

    match n.category {
        TokNumOp { ref op_name, .. } => {
            if n.childs.len() != 2 {
                panic!("Numeric operators need two arguments!")
            }
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);
            let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
            eval_num_op(&eval0, &eval1, &**op_name, code, temp_ids)
        },
        TokCompOp { ref op_name, .. } => {
            if n.childs.len() != 2 {
                panic!("Numeric operators need two arguments!")
            }
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);
            let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
            eval_comp_op(&eval0, &eval1, &**op_name, code, temp_ids, manager)
        },
        TokLogOp { ref op_name, .. } => {
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);

            match &**op_name {
                "and" | "or" => {
                    let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
                    eval_and_or(&eval0, &eval1, &**op_name, code, temp_ids)
                },
                "not" => {
                    eval_not(&eval0, code, temp_ids, manager)
                },
                _ => panic!("unhandled op")
            }
        }
        TokInt { ref value, .. } => {
            Operand::new_large_const(*value as i16)
        },
        TokBoolean { ref value, .. } => {
            boolstr_to_const(&**value)
        },
        TokString {ref value, .. } => {
            Operand::new_string_ref(out.write_string(value) as i16)
        },
        TokVariable { ref name, .. } => {
            Operand::Var(manager.symbol_table.get_symbol_id(name))
        },
        TokFunction { ref name, .. } => {
            match &**name {
                "random" => {
                    let args = &node.as_default().childs;
                    if args.len() != 2 {
                        panic!("Function random only supports 2 args");
                    }

                    if args[0].as_default().childs.len() != 1 || args[1].as_default().childs.len() != 1 {
                        panic!("Unsupported Expression");
                    }

                    let from = &args[0].as_default().childs[0];
                    let to = &args[1].as_default().childs[0];

                    let from_value = evaluate_expression_internal(from, code, temp_ids, manager, &mut out);
                    let to_value = evaluate_expression_internal(to, code, temp_ids, manager, &mut out);
                    codegen::function_random(&from_value, &to_value, code, temp_ids)
                },
                _ => { panic!("Unsupported function: {}", name)}
            }
        },
        _ => panic!("unhandled token {:?}", n.category)
    }
}

fn eval_num_op<'a>(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>, temp_ids: &mut Vec<u8>) -> Operand {
    if count_constants(eval0, eval1) == 2 {
        return direct_eval_num_op(eval0, eval1, op_name);
    }
    let save_var = determine_save_var(eval0, eval1, temp_ids);
    match op_name {
        "+" => {
            code.push(ZOP::Add{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "-" => {
            code.push(ZOP::Sub{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "*" => {
            code.push(ZOP::Mul{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "/" => {
            code.push(ZOP::Div{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "%" => {
            code.push(ZOP::Mod{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        _ => panic!("unhandled op")
    };

    free_var_if_both_temp(eval0, eval1, temp_ids);

    Operand::Var(save_var)
}

fn direct_eval_num_op(eval0: &Operand, eval1: &Operand, op_name: &str) -> Operand {
    let mut out_large = false;
    let val0 = eval0.const_value();
    let val1 = eval1.const_value();
    match eval0 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
    match eval1 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
    let result = match op_name {
        "+" => {
            val0 + val1
        },
        "-" => {
            val0 - val1
        },
        "*" => {
            val0 * val1
        },
        "/" => {
            val0 / val1
        },
        "%" => {
            val0 % val1
        },
        _ => panic!("unhandled op")
    };
    if out_large {
        Operand::LargeConst(LargeConstant { value: result })
    } else {
        Operand::Const(Constant { value: result as u8 })
    }
}

fn eval_comp_op<'a>(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>) -> Operand {
    if count_constants(eval0, eval1) == 2 {
        return direct_eval_comp_op(eval0, eval1, op_name);
    }
    let save_var = Variable::new(temp_ids.pop().unwrap());
    let label = format!("expr_{}", manager.ids_expr.start_next());
    let const_true = Operand::new_const(1);
    let const_false = Operand::new_const(0);
    match op_name {
        "is" | "==" | "eq" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
            code.push(ZOP::JE{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        "neq" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JE{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        "<" | "lt" =>  {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true });
            code.push(ZOP::JL{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        "<=" | "lte" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JG{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        ">=" | "gte" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JL{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        ">" | "gt" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
            code.push(ZOP::JG{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        _ => panic!("unhandled op")
    };
    code.push(ZOP::Label {name: label.to_string()});
    free_var_if_temp(eval0, temp_ids);
    free_var_if_temp(eval1, temp_ids);
    Operand::Var(save_var)
}

/// Directly evaluates the given compare operation.
/// Both operands must be constants.
fn direct_eval_comp_op(eval0: &Operand, eval1: &Operand, op_name: &str) -> Operand {
    let val0 = eval0.const_value();
    let val1 = eval1.const_value();
    let result = match op_name {
        "is" | "==" | "eq" => { val0 == val1 },
        "neq" => { val0 != val1 },
        "<" | "lt" =>  { val0 < val1 },
        "<=" | "lte" => { val0 <= val1 },
        ">=" | "gte" => { val0 >= val1 },
        ">" | "gt" => { val0 > val1 },
        _ => panic!("unhandled op")
    };
    if result {
        Operand::Const(Constant {value: 1})
    } else {
        Operand::Const(Constant {value: 0})
    }
}

fn eval_and_or(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>) -> Operand {
    if count_constants(&eval0, &eval1) == 2 {
        let mut out_large = false;
        let val0 = eval0.const_value();
        let val1 = eval1.const_value();
        match eval0 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
        match eval1 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
        let result = if op_name == "or" {
                val0 | val1
            } else {
                val0 & val1
            };
        if out_large {
            return Operand::LargeConst(LargeConstant { value: result })
        } else {
            return Operand::Const(Constant { value: result as u8 })
        }
    }

    let save_var = determine_save_var(eval0, eval1, temp_ids);
    if op_name == "or" {
        code.push(ZOP::Or{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
    } else {
        code.push(ZOP::And{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
    }
    free_var_if_both_temp(eval0, eval1, temp_ids);
    Operand::Var(save_var)
}

fn eval_not<'a>(eval: &Operand, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>) -> Operand {
    if eval.is_const() {
        let val = eval.const_value();
        let result: u8 = if val > 0 { 0 } else { 1 };
        return Operand::Const(Constant { value: result });
    }
    let save_var = Variable::new(temp_ids.pop().unwrap());
    let label = format!("expr_{}", manager.ids_expr.start_next());
    code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: Operand::new_const(0)});
    code.push(ZOP::JG{operand1: eval.clone(), operand2: Operand::new_const(0), jump_to_label: label.to_string()});
    code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: Operand::new_const(1)});
    code.push(ZOP::Label {name: label.to_string()});
    free_var_if_temp(eval, temp_ids);
    Operand::Var(save_var)
}

fn free_var_if_both_temp (eval0: &Operand, eval1: &Operand, temp_ids: &mut Vec<u8>) {
    match eval0 {
        &Operand::Var(ref var1) => {
            if CodeGenManager::is_temp_var(var1) {
                match eval1 {
                    &Operand::Var(ref var2)=> {
                        if CodeGenManager::is_temp_var(var2) {
                            temp_ids.push(var2.id);
                        }
                    }, _ => {}
                }
            }
        }, _ => {}
    };
}

fn free_var_if_temp (operand: &Operand, temp_ids: &mut Vec<u8>) {
    match operand {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var){
                temp_ids.push(var.id);
            }
        }, _ => {}
    }
}

fn determine_save_var(operand1: &Operand, operand2: &Operand, temp_ids: &mut Vec<u8>) -> Variable {
    match operand1 {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var) {
                return var.clone();
            }
        }, _ => {}
    };
    match operand2 {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var) {
                return var.clone();
            }
        }, _ => {}
    };
    return Variable::new(temp_ids.pop().unwrap());
}

fn count_constants(operand1: &Operand, operand2: &Operand) -> u8 {
    let mut const_count: u8 = 0;
    if operand1.is_const() {
        const_count += 1;
    }
    if operand2.is_const() {
        const_count += 1;
    }
    const_count
}

fn boolstr_to_const(string: &str) -> Operand {
    match string {
        "true" => Operand::Const(Constant { value: 1 }),
        _ => Operand::Const(Constant { value: 0 })
    }
}
<commit_msg>Add translation of unary minus from ast to zcode<commit_after>//! The `evaluate_expressions` module...

use backend::zcode::zfile::{ZOP, Operand, Variable, Constant, LargeConstant, Zfile};
use frontend::ast::{ASTNode};
use frontend::codegen;
use frontend::codegen::{CodeGenManager};
use frontend::lexer::Token::{TokNumOp, TokCompOp, TokLogOp, TokInt, TokBoolean, TokVariable, TokFunction, TokString, TokUnaryMinus};

pub fn evaluate_expression<'a>(node: &'a ASTNode, code: &mut Vec<ZOP>, mut manager: &mut CodeGenManager<'a>, mut out: &mut Zfile) -> Operand {
    let mut temp_ids = CodeGenManager::new_temp_var_vec();
    evaluate_expression_internal(node, code, &mut temp_ids, manager, &mut out)
}

/// Evaluates an expression node to zCode.
fn evaluate_expression_internal<'a>(node: &'a ASTNode, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>, mut out: &mut Zfile) -> Operand {
    let n = node.as_default();

    match n.category {
        TokNumOp { ref op_name, .. } => {
            if n.childs.len() != 2 {
                panic!("Numeric operators need two arguments!")
            }
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);
            let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
            eval_num_op(&eval0, &eval1, &**op_name, code, temp_ids)
        },
        TokCompOp { ref op_name, .. } => {
            if n.childs.len() != 2 {
                panic!("Numeric operators need two arguments!")
            }
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);
            let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
            eval_comp_op(&eval0, &eval1, &**op_name, code, temp_ids, manager)
        },
        TokLogOp { ref op_name, .. } => {
            let eval0 = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);

            match &**op_name {
                "and" | "or" => {
                    let eval1 = evaluate_expression_internal(&n.childs[1], code, temp_ids, manager, &mut out);
                    eval_and_or(&eval0, &eval1, &**op_name, code, temp_ids)
                },
                "not" => {
                    eval_not(&eval0, code, temp_ids, manager)
                },
                _ => panic!("unhandled op")
            }
        },
        TokUnaryMinus { .. } => {
            let eval = evaluate_expression_internal(&n.childs[0], code, temp_ids, manager, &mut out);
            eval_unary_minus(&eval, code, temp_ids)
        },
        TokInt { ref value, .. } => {
            Operand::new_large_const(*value as i16)
        },
        TokBoolean { ref value, .. } => {
            boolstr_to_const(&**value)
        },
        TokString {ref value, .. } => {
            Operand::new_string_ref(out.write_string(value) as i16)
        },
        TokVariable { ref name, .. } => {
            Operand::Var(manager.symbol_table.get_symbol_id(name))
        },
        TokFunction { ref name, .. } => {
            match &**name {
                "random" => {
                    let args = &node.as_default().childs;
                    if args.len() != 2 {
                        panic!("Function random only supports 2 args");
                    }

                    if args[0].as_default().childs.len() != 1 || args[1].as_default().childs.len() != 1 {
                        panic!("Unsupported Expression");
                    }

                    let from = &args[0].as_default().childs[0];
                    let to = &args[1].as_default().childs[0];

                    let from_value = evaluate_expression_internal(from, code, temp_ids, manager, &mut out);
                    let to_value = evaluate_expression_internal(to, code, temp_ids, manager, &mut out);
                    codegen::function_random(&from_value, &to_value, code, temp_ids)
                },
                _ => { panic!("Unsupported function: {}", name)}
            }
        },
        _ => panic!("unhandled token {:?}", n.category)
    }
}

fn eval_num_op<'a>(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>, temp_ids: &mut Vec<u8>) -> Operand {
    if count_constants(eval0, eval1) == 2 {
        return direct_eval_num_op(eval0, eval1, op_name);
    }
    let save_var = determine_save_var(eval0, eval1, temp_ids);
    match op_name {
        "+" => {
            code.push(ZOP::Add{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "-" => {
            code.push(ZOP::Sub{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "*" => {
            code.push(ZOP::Mul{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "/" => {
            code.push(ZOP::Div{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        "%" => {
            code.push(ZOP::Mod{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
        },
        _ => panic!("unhandled op")
    };

    free_var_if_both_temp(eval0, eval1, temp_ids);

    Operand::Var(save_var)
}

fn direct_eval_num_op(eval0: &Operand, eval1: &Operand, op_name: &str) -> Operand {
    let mut out_large = false;
    let val0 = eval0.const_value();
    let val1 = eval1.const_value();
    match eval0 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
    match eval1 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
    let result = match op_name {
        "+" => {
            val0 + val1
        },
        "-" => {
            val0 - val1
        },
        "*" => {
            val0 * val1
        },
        "/" => {
            val0 / val1
        },
        "%" => {
            val0 % val1
        },
        _ => panic!("unhandled op")
    };
    if out_large {
        Operand::LargeConst(LargeConstant { value: result })
    } else {
        Operand::Const(Constant { value: result as u8 })
    }
}

fn eval_comp_op<'a>(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>) -> Operand {
    if count_constants(eval0, eval1) == 2 {
        return direct_eval_comp_op(eval0, eval1, op_name);
    }
    let save_var = Variable::new(temp_ids.pop().unwrap());
    let label = format!("expr_{}", manager.ids_expr.start_next());
    let const_true = Operand::new_const(1);
    let const_false = Operand::new_const(0);
    match op_name {
        "is" | "==" | "eq" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
            code.push(ZOP::JE{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        "neq" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JE{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        "<" | "lt" =>  {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true });
            code.push(ZOP::JL{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        "<=" | "lte" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JG{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        ">=" | "gte" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
            code.push(ZOP::JL{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
        },
        ">" | "gt" => {
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_true});
            code.push(ZOP::JG{operand1: eval0.clone(), operand2: eval1.clone(), jump_to_label: label.to_string()});
            code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: const_false});
        },
        _ => panic!("unhandled op")
    };
    code.push(ZOP::Label {name: label.to_string()});
    free_var_if_temp(eval0, temp_ids);
    free_var_if_temp(eval1, temp_ids);
    Operand::Var(save_var)
}

/// Directly evaluates the given compare operation.
/// Both operands must be constants.
fn direct_eval_comp_op(eval0: &Operand, eval1: &Operand, op_name: &str) -> Operand {
    let val0 = eval0.const_value();
    let val1 = eval1.const_value();
    let result = match op_name {
        "is" | "==" | "eq" => { val0 == val1 },
        "neq" => { val0 != val1 },
        "<" | "lt" =>  { val0 < val1 },
        "<=" | "lte" => { val0 <= val1 },
        ">=" | "gte" => { val0 >= val1 },
        ">" | "gt" => { val0 > val1 },
        _ => panic!("unhandled op")
    };
    if result {
        Operand::Const(Constant {value: 1})
    } else {
        Operand::Const(Constant {value: 0})
    }
}

fn eval_and_or(eval0: &Operand, eval1: &Operand, op_name: &str, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>) -> Operand {
    if count_constants(&eval0, &eval1) == 2 {
        let mut out_large = false;
        let val0 = eval0.const_value();
        let val1 = eval1.const_value();
        match eval0 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
        match eval1 { &Operand::LargeConst(_) => {out_large = true; }, _ => {} };
        let result = if op_name == "or" {
                val0 | val1
            } else {
                val0 & val1
            };
        if out_large {
            return Operand::LargeConst(LargeConstant { value: result })
        } else {
            return Operand::Const(Constant { value: result as u8 })
        }
    }

    let save_var = determine_save_var(eval0, eval1, temp_ids);
    if op_name == "or" {
        code.push(ZOP::Or{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
    } else {
        code.push(ZOP::And{operand1: eval0.clone(), operand2: eval1.clone(), save_variable: save_var.clone()});
    }
    free_var_if_both_temp(eval0, eval1, temp_ids);
    Operand::Var(save_var)
}

fn eval_not<'a>(eval: &Operand, code: &mut Vec<ZOP>,
        temp_ids: &mut Vec<u8>, mut manager: &mut CodeGenManager<'a>) -> Operand {
    if eval.is_const() {
        let val = eval.const_value();
        let result: u8 = if val > 0 { 0 } else { 1 };
        return Operand::Const(Constant { value: result });
    }
    let save_var = Variable::new(temp_ids.pop().unwrap());
    let label = format!("expr_{}", manager.ids_expr.start_next());
    code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: Operand::new_const(0)});
    code.push(ZOP::JG{operand1: eval.clone(), operand2: Operand::new_const(0), jump_to_label: label.to_string()});
    code.push(ZOP::StoreVariable{ variable: save_var.clone(), value: Operand::new_const(1)});
    code.push(ZOP::Label {name: label.to_string()});
    free_var_if_temp(eval, temp_ids);
    Operand::Var(save_var)
}

fn eval_unary_minus(eval: &Operand, code: &mut Vec<ZOP>, temp_ids: &mut Vec<u8>) -> Operand {
    if eval.is_const() {
        let large = match eval { &Operand::LargeConst(_) => { true }, _ => { false } };
        if large {
            return Operand::new_large_const(-eval.const_value());
        } else {
            return Operand::new_const(-eval.const_value() as u8);
        }
    }

    let save_var = match eval {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var) {
                Variable::new(var.id)
            } else {
                Variable::new(temp_ids.pop().unwrap())
            }
        }, _ => { Variable::new(temp_ids.pop().unwrap()) }
    };

    code.push(ZOP::Sub {operand1: Operand::new_const(0), operand2: eval.clone(), save_variable: save_var.clone()});

    Operand::new_var(save_var.id)
}

fn free_var_if_both_temp (eval0: &Operand, eval1: &Operand, temp_ids: &mut Vec<u8>) {
    match eval0 {
        &Operand::Var(ref var1) => {
            if CodeGenManager::is_temp_var(var1) {
                match eval1 {
                    &Operand::Var(ref var2)=> {
                        if CodeGenManager::is_temp_var(var2) {
                            temp_ids.push(var2.id);
                        }
                    }, _ => {}
                }
            }
        }, _ => {}
    };
}

fn free_var_if_temp (operand: &Operand, temp_ids: &mut Vec<u8>) {
    match operand {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var){
                temp_ids.push(var.id);
            }
        }, _ => {}
    }
}

fn determine_save_var(operand1: &Operand, operand2: &Operand, temp_ids: &mut Vec<u8>) -> Variable {
    match operand1 {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var) {
                return var.clone();
            }
        }, _ => {}
    };
    match operand2 {
        &Operand::Var(ref var) => {
            if CodeGenManager::is_temp_var(var) {
                return var.clone();
            }
        }, _ => {}
    };
    return Variable::new(temp_ids.pop().unwrap());
}

fn count_constants(operand1: &Operand, operand2: &Operand) -> u8 {
    let mut const_count: u8 = 0;
    if operand1.is_const() {
        const_count += 1;
    }
    if operand2.is_const() {
        const_count += 1;
    }
    const_count
}

fn boolstr_to_const(string: &str) -> Operand {
    match string {
        "true" => Operand::Const(Constant { value: 1 }),
        _ => Operand::Const(Constant { value: 0 })
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

/// # Mutable Iterators
///
/// We will implement a simple tree that could, say, represent a simple DOM
/// structure.  You may notice that we don't actually allow for text in our
/// simple representation, but this isn't important here, what we really want
/// to investigate is how we would implement a mutable iterator using our custom
/// data structure.  Our DOM structure will only allow for four different types
/// of nodes: Header, Paragraph, Text, and Images.

enum NodeType {
    Header,
    Paragraph,
    Text,
    Image,
}

/// Each node with have a list of `children` nodes and a tag for the respective
/// DOM element type.

struct DomNode {
    children: Vec<DomNode>,
    node_type: NodeType
}

/// To implement an iterator, we essentially just need to tell Rust two things:
///   a. What kind of elements will we be iteratorating over?  In this example
///      we will be iteratorating over the nodes of our Dom, so we will want
///      to iterate over `NodeType`s.
///   b. What is the next element?
///
/// We will therefore have the responsibility of keeping track of where we are at
/// while iteratorating over our DOM.  We will do this by constructing what is
/// oftern called an "iterator interface".  We make one like this:

struct DomMutIterator<'a> {
    data: &'a mut DomNode,
    cursor: usize,
}

/// We provide answers for the questions posted above for Rust by implementing an
/// `Iterator` for our iterator interface.

impl<'a> Iterator for DomMutIterator<'a> {
    type Item = &'a mut NodeType;
    fn next(&mut self) -> Option<&'a mut NodeType> {

        // This part will require some thought...

        unimplemented!();
    }
}

fn main() {
}

/// Note: Rust implementation of creating a mutable iterator uses a `Range` object which, keeps track of the size of the vector.
/// this allows for unchecked boundes [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).
/// we should leave this as an exercise to the reader and show them the source to reference. They use the `Range` object to call the
/// recurse in the vector [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).  Perhaps
/// this might be a good idea for us as well.
<commit_msg>change comment style to make it easier to transition to md<commit_after>#![allow(dead_code)]

// # Mutable Iterators

//
// We will implement a simple tree that could, say, represent a simple DOM
// structure.  You may notice that we don't actually allow for text in our
// simple representation, but this isn't important here, what we really want
// to investigate is how we would implement a mutable iterator using our custom
// data structure.  Our DOM structure will only allow for four different types
// of nodes: Header, Paragraph, Text, and Images.

enum NodeType {
    Header,
    Paragraph,
    Text,
    Image,
}

// Each node with have a list of `children` nodes and a tag for the respective
// DOM element type.

struct DomNode {
    children: Vec<DomNode>,
    node_type: NodeType
}

// To implement an iterator, we essentially just need to tell Rust two things:
//   a. What kind of elements will we be iteratorating over?  In this example
//      we will be iteratorating over the nodes of our Dom, so we will want
//      to iterate over `NodeType`s.
//   b. What is the next element?
//
// We will therefore have the responsibility of keeping track of where we are at
// while iteratorating over our DOM.  We will do this by constructing what is
// oftern called an "iterator interface".  We make one like this:

struct DomMutIterator<'a> {
    data: &'a mut DomNode,
    cursor: usize,
}

// We provide answers for the questions posted above for Rust by implementing an
// `Iterator` for our iterator interface.

impl<'a> Iterator for DomMutIterator<'a> {
    type Item = &'a mut NodeType;
    fn next(&mut self) -> Option<&'a mut NodeType> {

        // This part will require some thought...

        unimplemented!();
    }
}

fn main() {
}

// Note: Rust implementation of creating a mutable iterator uses a `Range` object which, keeps track of the size of the vector.
// this allows for unchecked boundes [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).
// we should leave this as an exercise to the reader and show them the source to reference. They use the `Range` object to call the
// recurse in the vector [see here](https://doc.rust-lang.org/src/collections/up/src/libcollections/btree/map.rs.html#920).  Perhaps
// this might be a good idea for us as well.
<|endoftext|>


<commit_before>extern crate "parser-combinators" as parser_combinators;
use self::parser_combinators::{between, spaces, many, satisfy, Parser, ParserExt, ParseResult};
use self::parser_combinators::primitives::{State, Stream};
use super::ast::*;
use super::ast::ExprNode::*;

pub fn name<I>(input: State<I>) -> ParseResult<NameNode, I>
    where I: Stream<Item=char> {
         let initial = satisfy(|c|
            c.is_alphabetic()
                || c == '='
                || c == '*'
                || c == '+'
                || c == '/'
                || c == '!'
                || c == '\\'
                || c == '?');
        let subsequent = satisfy(|c|
            c.is_alphanumeric()
                || c == '='
                || c == '*'
                || c == '+'
                || c == '/'
                || c == '!'
                || c == '\\'
                || c == '?');
        initial
            .and(many::<Vec<_>, _>(subsequent).map(|it|
                it.iter().fold(
                    String::new(),
                    |mut s: String, i| {
                        s.push(*i);
                        s
                    }
                    )
                ))
            .parse_state(input)
            .map(|x| {
                let mut s = String::new();
                s.push((x.0).0);
                s.push_str(&(x.0).1);
                (NameNode{ name: s}, x.1)
            })
}

pub fn expr<I>(input: State<I>) -> ParseResult<ExprNode, I>
    where I: Stream<Item=char> {
        let spaces = spaces();
        let sexpr = between(
            satisfy(|c| c == '('),
            satisfy(|c| c == ')'),
            (name as fn(_) -> _)
                .and(many(expr as fn(_) -> _))
                .map(|x| {
                    SExpr(SExprNode {
                        operator: x.0,
                        operands: (x.1)
                    })
                })
                );
        spaces.clone().with(
            sexpr
                .or((name as fn(_) -> _).map(Name))
            ).parse_state(input)
}

#[cfg(test)]
mod tests {
    use ::ast::*;
    use ::ast::ExprNode::*;
    use super::expr;
    use super::parser_combinators::Parser;

    #[test]
    fn test_basic_ident() {
        assert_eq!(
            (expr as fn (_) -> _).parse("ident").unwrap(),
            (Name(NameNode { name: "ident".to_string() }), "")
            );
    }

        #[test]
    fn test_basic_sexpr() {
        assert_eq!(
            (expr as fn (_) -> _).parse("(ident arg1 arg2)").unwrap(),
            (SExpr(SExprNode {
                operator: NameNode { name: "ident".to_string() },
                operands: vec![
                    Name(NameNode { name: "arg1".to_string() }),
                    Name(NameNode { name: "arg2".to_string() })
                ]
            }), "")
            );
    }

}
<commit_msg>Update ident parser to be fully R6RS compliant<commit_after>extern crate "parser-combinators" as parser_combinators;
use self::parser_combinators::{between, spaces, digit, many, satisfy, Parser, ParserExt, ParseResult};
use self::parser_combinators::primitives::{State, Stream};
use super::ast::*;
use super::ast::ExprNode::*;

pub fn name<I>(input: State<I>) -> ParseResult<NameNode, I>
    where I: Stream<Item=char> {
         let initial = satisfy(|c|
            c.is_alphabetic()
                // R6RS 'special initial' characters
                || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                || c == '?');
        let subsequent = satisfy(|c|
            c.is_alphanumeric()
                // R6RS 'special initial' characters
                || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                || c == '?'
                // R6RS 'special subsequent' characters
                || c == '+' || c == '-' || c == '.' || c == '@');
        initial
            .and(many::<Vec<_>, _>(subsequent).map(|it|
                it.iter().fold(
                    String::new(),
                    |mut s: String, i| {
                        s.push(*i);
                        s
                    }
                    )
                ))
            .parse_state(input)
            .map(|x| {
                let mut s = String::new();
                s.push((x.0).0);
                s.push_str(&(x.0).1);
                (NameNode{ name: s}, x.1)
            })
}

pub fn expr<I>(input: State<I>) -> ParseResult<ExprNode, I>
    where I: Stream<Item=char> {
        let spaces = spaces();
        let sexpr = between(
            satisfy(|c| c == '('),
            satisfy(|c| c == ')'),
            (name as fn(_) -> _)
                .and(many(expr as fn(_) -> _))
                .map(|x| {
                    SExpr(SExprNode {
                        operator: x.0,
                        operands: (x.1)
                    })
                })
                );
        spaces.clone().with(
            sexpr
                .or((name as fn(_) -> _).map(Name))
            ).parse_state(input)
}

#[cfg(test)]
mod tests {
    use ::ast::*;
    use ::ast::ExprNode::*;
    use super::expr;
    use super::parser_combinators::Parser;

    #[test]
    fn test_basic_ident() {
        assert_eq!(
            (expr as fn (_) -> _).parse("ident").unwrap(),
            (Name(NameNode { name: "ident".to_string() }), "")
            );
    }

        #[test]
    fn test_basic_sexpr() {
        assert_eq!(
            (expr as fn (_) -> _).parse("(ident arg1 arg2)").unwrap(),
            (SExpr(SExprNode {
                operator: NameNode { name: "ident".to_string() },
                operands: vec![
                    Name(NameNode { name: "arg1".to_string() }),
                    Name(NameNode { name: "arg2".to_string() })
                ]
            }), "")
            );
    }

}
<|endoftext|>


<commit_before>use rustyline::error::ReadlineError;
use rustyline::validate::{ValidationContext, ValidationResult, Validator};
use rustyline::Editor;
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};

#[derive(Completer, Helper, Highlighter, Hinter)]
struct InputValidator {}

impl Validator for InputValidator {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult, ReadlineError> {
        let input = ctx.input();
        if !input.starts_with("SELECT") {
            return Ok(ValidationResult::Invalid(Some(
                " --< Expect: SELECT stmt".to_owned(),
            )));
        } else if !input.ends_with(';') {
            return Ok(ValidationResult::Incomplete);
        }
        Ok(ValidationResult::Valid(None))
    }
}

fn main() -> rustyline::Result<()> {
    let h = InputValidator {};
    let mut rl = Editor::new();
    rl.set_helper(Some(h));

    let input = rl.readline("> ")?;
    println!("Input: {}", input);
    Ok(())
}
<commit_msg>Simplify syntax<commit_after>use rustyline::error::ReadlineError;
use rustyline::validate::{ValidationContext, ValidationResult, Validator};
use rustyline::Editor;
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};

#[derive(Completer, Helper, Highlighter, Hinter)]
struct InputValidator {}

impl Validator for InputValidator {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult, ReadlineError> {
        use ValidationResult::{Incomplete,Invalid, Valid};
        let input = ctx.input();
        let result = if !input.starts_with("SELECT") {
            Invalid(Some(" --< Expect: SELECT stmt".to_owned()))
        } else if !input.ends_with(';') {
            Incomplete
        } else {
            Valid(None)
        };
        Ok(result)
    }
}

fn main() -> rustyline::Result<()> {
    let h = InputValidator {};
    let mut rl = Editor::new();
    rl.set_helper(Some(h));

    let input = rl.readline("> ")?;
    println!("Input: {}", input);
    Ok(())
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use self::Needed::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

impl Needed {
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
  #[inline]
  pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Size(f(n)),
    }
  }
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
  /// to a contained `Incomplete` value, leaving `Done` and `Error` value
  /// untouched.
  #[inline]
  pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
   where F: FnOnce(Needed) -> Needed {
    match self {
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(f(n)),
      Done(i, o)    => Done(i, o),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn needed_map() {
    let unknown = Needed::Unknown;
    let size = Needed::Size(5);

    assert_eq!(size.map(|x| x * 2), Needed::Size(10));
    assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
  }

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_inc() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
    let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));

    assert_eq!(done.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
    assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<commit_msg>remove some warnings<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use self::Needed::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

impl Needed {
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
  #[inline]
  pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Size(f(n)),
    }
  }
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
  /// to a contained `Incomplete` value, leaving `Done` and `Error` value
  /// untouched.
  #[inline]
  pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
   where F: FnOnce(Needed) -> Needed {
    match self {
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(f(n)),
      Done(i, o)    => Done(i, o),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn needed_map() {
    let unknown = Needed::Unknown;
    let size = Needed::Size(5);

    assert_eq!(size.map(|x| x * 2), Needed::Size(10));
    assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
  }

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_inc() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
    let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));

    assert_eq!(done.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
    assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Incomplete(Needed::Unknown));
  }
}
<|endoftext|>


<commit_before>extern mod std;
extern mod encoding;

use std::net::ip;
use std::net::tcp;
use std::uv_global_loop;

use encoding::{Codec};
use io::{ReaderUtil, WriterUtil};
use tcp::{TcpErrData, TcpNewConnection, TcpSocket};
use task::{SingleThreaded, task};

type KillChan = comm::Chan<Option<TcpErrData>>;
type ContChan = comm::Chan<()>;

fn main() {
    let iotask = uv_global_loop::get();

    let addr = "127.0.0.1";
    let port = 1337;

    let backlog = 128;
    let ip_addr = ip::get_addr(addr, iotask);
    let ip_addr = copy result::unwrap(move ip_addr)[0];

    tcp::listen(move ip_addr, port, backlog, iotask,
        |kill_ch| on_established(kill_ch),
        |conn, kill_ch| on_new_connection(conn, kill_ch));
}

fn on_established(_kill_ch: KillChan) {
    io::println("running at 127.0.0.1:1337");
}

fn on_new_connection(conn: TcpNewConnection, kill_ch: KillChan) {
    do comm::listen |cont_ch| {
        // Spawn new child which doesn't propagate errors to parent.
        do task().unlinked().sched_mode(SingleThreaded).spawn {
            accept(conn, kill_ch, cont_ch);
        }
        // Wait `tcp::accept(conn)' complete.
        cont_ch.recv();
    }
}

fn accept(conn: TcpNewConnection, kill_ch: KillChan, cont_ch: ContChan) {
    match tcp::accept(conn) {
        Ok(move socket) => {
            cont_ch.send(());
            encode(move socket);
        }
        Err(move err_data) => {
            kill_ch.send(Some(move err_data));
            cont_ch.send(());
        }
    }
}

fn encode(socket: TcpSocket) {
    let socket = tcp::socket_buf(move socket);

    let mut chunk = ~[];
    let mut buf = [mut 0, ..1024];

    loop {
        let nread = socket.read(buf, buf.len());
        if nread == 0 {
            break;
        }
        chunk.push_all(buf.view(0, nread));
    }

    let encoded_bytes = chunk.encode(encoding::Base64);

    socket.write(encoded_bytes);
}
<commit_msg>examples: Use io::with_bytes_writer and Base64Writer<commit_after>extern mod std;
extern mod encoding;

use std::net::ip;
use std::net::tcp;
use std::uv_global_loop;

use encoding::{BASE64, Base64Writer};
use io::{ReaderUtil, WriterUtil};
use tcp::{TcpErrData, TcpNewConnection, TcpSocket};
use task::{SingleThreaded, task};

type KillChan = comm::Chan<Option<TcpErrData>>;
type ContChan = comm::Chan<()>;

fn main() {
    let iotask = uv_global_loop::get();

    let addr = "127.0.0.1";
    let port = 1337;

    let backlog = 128;
    let ip_addr = ip::get_addr(addr, iotask);
    let ip_addr = copy result::unwrap(move ip_addr)[0];

    tcp::listen(move ip_addr, port, backlog, iotask,
        |kill_ch| on_established(kill_ch),
        |conn, kill_ch| on_new_connection(conn, kill_ch));
}

fn on_established(_kill_ch: KillChan) {
    io::println("running at 127.0.0.1:1337");
}

fn on_new_connection(conn: TcpNewConnection, kill_ch: KillChan) {
    do comm::listen |cont_ch| {
        // Spawn new child which doesn't propagate errors to parent.
        do task().unlinked().sched_mode(SingleThreaded).spawn {
            accept(conn, kill_ch, cont_ch);
        }
        // Wait `tcp::accept(conn)' complete.
        cont_ch.recv();
    }
}

fn accept(conn: TcpNewConnection, kill_ch: KillChan, cont_ch: ContChan) {
    match tcp::accept(conn) {
        Ok(move socket) => {
            cont_ch.send(());
            encode(move socket);
        }
        Err(move err_data) => {
            kill_ch.send(Some(move err_data));
            cont_ch.send(());
        }
    }
}

fn encode(socket: TcpSocket) {
    let socket = tcp::socket_buf(move socket);

    let encoded_bytes = io::with_bytes_writer(|writer| {
        let writer = Base64Writer(BASE64, move writer);
        let mut buf = [mut 0, ..1024];
        loop {
            let nread = socket.read(buf, buf.len());
            if nread == 0 { break; }
            writer.write(buf.view(0, nread));
        }
        // FIXME: Remove this line once we get Drop trait.
        writer.close();
    });

    socket.write(encoded_bytes);
}
<|endoftext|>