<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor::PipelineLayout;
//use descriptor::pipeline_layout::PipelineLayoutDesc;
//use descriptor::pipeline_layout::PipelineLayoutSuperset;
use pipeline::shader::ComputeShaderEntryPoint;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

///
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Arc<Pl>,
}

impl<Pl> ComputePipeline<Pl> {
    ///
    ///
    /// # Panic
    ///
    /// Panicks if the pipeline layout and/or shader don't belong to the device.
    pub fn new<Css, Csl>(device: &Arc<Device>, pipeline_layout: &Arc<Pl>,
                         shader: &ComputeShaderEntryPoint<Css, Csl>)
                         -> Result<Arc<ComputePipeline<Pl>>, OomError>
        where Pl: PipelineLayout// + PipelineLayoutSuperset<Csl>, Csl: PipelineLayoutDesc
    {
        let vk = device.pointers();

        // TODO: should be an error instead
        //assert!(PipelineLayoutSuperset::is_superset_of(pipeline_layout, shader));

        let pipeline = unsafe {
            /*let spec_descriptors = specialization.descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len(),
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const S as *const _,
            };*/

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: //if mem::size_of_val(specialization) == 0 {
                    ptr::null()
                /*} else {
                    &specialization
                }*/,
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: PipelineLayout::inner_pipeline_layout(&**pipeline_layout).internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout.clone(),
        }))
    }

    /// Returns the `Device` this compute pipeline was created with.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the pipeline layout used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Arc<Pl> {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<commit_msg>Restore specialization constants when building a compute pipeline<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor::PipelineLayout;
//use descriptor::pipeline_layout::PipelineLayoutDesc;
//use descriptor::pipeline_layout::PipelineLayoutSuperset;
use pipeline::shader::ComputeShaderEntryPoint;
use pipeline::shader::SpecializationConstants;

use device::Device;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

///
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Arc<Pl>,
}

impl<Pl> ComputePipeline<Pl> {
    ///
    ///
    /// # Panic
    ///
    /// Panicks if the pipeline layout and/or shader don't belong to the device.
    pub fn new<Css, Csl>(device: &Arc<Device>, pipeline_layout: &Arc<Pl>,
                         shader: &ComputeShaderEntryPoint<Css, Csl>, specialization: &Css)
                         -> Result<Arc<ComputePipeline<Pl>>, OomError>
        where Pl: PipelineLayout,// + PipelineLayoutSuperset<Csl>, Csl: PipelineLayoutDesc,
              Css: SpecializationConstants
    {
        let vk = device.pointers();

        // TODO: should be an error instead
        //assert!(PipelineLayoutSuperset::is_superset_of(pipeline_layout, shader));

        let pipeline = unsafe {
            let spec_descriptors = <Css as SpecializationConstants>::descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len() as u32,
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const Css as *const _,
            };

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: if specialization.dataSize == 0 {
                    ptr::null()
                } else {
                    &specialization
                },
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: PipelineLayout::inner_pipeline_layout(&**pipeline_layout).internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout.clone(),
        }))
    }

    /// Returns the `Device` this compute pipeline was created with.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the pipeline layout used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Arc<Pl> {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<|endoftext|>


<commit_before>//! An example of how to draw to `Image`'s using the `Canvas` type.

use ggez;
use glam;

use ggez::event;
use ggez::graphics::{self, Color, DrawParam};
use ggez::{Context, GameResult};

type Point2 = glam::Vec2;
type Vector2 = glam::Vec2;

struct MainState {
    canvas: graphics::Canvas,
    text: graphics::Text,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let canvas = graphics::Canvas::with_window_size(ctx)?;
        let font = graphics::Font::default();
        let text = graphics::Text::new(("Hello world!", font, 24.0));
        Ok(MainState { canvas, text })
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        // first lets render to our canvas
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        graphics::draw(
            ctx,
            &self.text,
            (Point2::new(400.0, 300.0), Color::WHITE),
        )?;

        // now lets render our scene once in the top left and in the bottom
        // right
        let window_size = graphics::size(ctx);
        let scale = Vector2::new(
            0.5 * window_size.0 as f32 / self.canvas.image().width() as f32,
            0.5 * window_size.1 as f32 / self.canvas.image().height() as f32,
        );
        // let scale = Vector2::new(1.0, 1.0);
        graphics::set_canvas(ctx, None);
        graphics::clear(ctx, Color::new(0.0, 0.0, 0.0, 1.0));
        graphics::draw(
            ctx,
            &self.canvas,
            DrawParam::default()
                .dest(Point2::new(0.0, 0.0))
                .scale(scale),
        )?;
        graphics::draw(
            ctx,
            &self.canvas,
            DrawParam::default()
                .dest(Point2::new(400.0, 300.0))
                .scale(scale),
        )?;
        graphics::present(ctx)?;

        Ok(())
    }

    fn resize_event(&mut self, ctx: &mut Context, width: f32, height: f32) {
        let new_rect = graphics::Rect::new(0.0, 0.0, width, height);
        graphics::set_screen_coordinates(ctx, new_rect).unwrap();
    }
}

pub fn main() -> GameResult {
    let cb = ggez::ContextBuilder::new("render_to_image", "ggez");
    let (mut ctx, event_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>Formatting<commit_after>//! An example of how to draw to `Image`'s using the `Canvas` type.

use ggez;
use glam;

use ggez::event;
use ggez::graphics::{self, Color, DrawParam};
use ggez::{Context, GameResult};

type Point2 = glam::Vec2;
type Vector2 = glam::Vec2;

struct MainState {
    canvas: graphics::Canvas,
    text: graphics::Text,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let canvas = graphics::Canvas::with_window_size(ctx)?;
        let font = graphics::Font::default();
        let text = graphics::Text::new(("Hello world!", font, 24.0));
        Ok(MainState { canvas, text })
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        // first lets render to our canvas
        graphics::set_canvas(ctx, Some(&self.canvas));
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        graphics::draw(ctx, &self.text, (Point2::new(400.0, 300.0), Color::WHITE))?;

        // now lets render our scene once in the top left and in the bottom
        // right
        let window_size = graphics::size(ctx);
        let scale = Vector2::new(
            0.5 * window_size.0 as f32 / self.canvas.image().width() as f32,
            0.5 * window_size.1 as f32 / self.canvas.image().height() as f32,
        );
        // let scale = Vector2::new(1.0, 1.0);
        graphics::set_canvas(ctx, None);
        graphics::clear(ctx, Color::new(0.0, 0.0, 0.0, 1.0));
        graphics::draw(
            ctx,
            &self.canvas,
            DrawParam::default()
                .dest(Point2::new(0.0, 0.0))
                .scale(scale),
        )?;
        graphics::draw(
            ctx,
            &self.canvas,
            DrawParam::default()
                .dest(Point2::new(400.0, 300.0))
                .scale(scale),
        )?;
        graphics::present(ctx)?;

        Ok(())
    }

    fn resize_event(&mut self, ctx: &mut Context, width: f32, height: f32) {
        let new_rect = graphics::Rect::new(0.0, 0.0, width, height);
        graphics::set_screen_coordinates(ctx, new_rect).unwrap();
    }
}

pub fn main() -> GameResult {
    let cb = ggez::ContextBuilder::new("render_to_image", "ggez");
    let (mut ctx, event_loop) = cb.build()?;
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before><commit_msg>finish rust version<commit_after><|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate claxon;
extern crate hound;

fn main() {
    use std::env;
    use std::fs;
    use std::io;
    use std::path;
    use claxon::FlacStream;
    use hound::{WavSpec, WavWriter};

    let arg = env::args().nth(1).unwrap();
    let fname = path::Path::new(&arg);
    let input = fs::File::open(fname).unwrap();
    let mut reader = io::BufReader::new(input);
    let mut stream = FlacStream::new(&mut reader).unwrap();
    let n_samples = stream.streaminfo().n_samples.unwrap();

    let spec = WavSpec {
        // TODO: naming is inconsistent between Hound and Claxon.
        // TODO: u8 for n_channels, is that weird? Would u32 be better?
        channels: stream.streaminfo().n_channels as u16,
        sample_rate: stream.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: stream.streaminfo().bits_per_sample as u16
    };
    let fname_wav = fname.with_extension("wav");
    let mut output = WavWriter::create(fname_wav, spec).unwrap();

    let mut blocks = stream.blocks::<i16>();
    let mut sample = 0u64;
    let mut i = 0u64;

    while sample < n_samples {
        let block = blocks.read_next().unwrap();
        let left = block.channel(0);
        let right = block.channel(1);
        for (&l, &r) in left.iter().zip(right.iter()) {
            output.write_sample(l).ok().expect("failed to write sample");
            output.write_sample(r).ok().expect("failed to write sample");
        }
        sample = sample + block.len() as u64;
        i = i + 1;
    }
}
<commit_msg>use i32 for decoding in debug executable<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate claxon;
extern crate hound;

fn main() {
    use std::env;
    use std::fs;
    use std::io;
    use std::path;
    use claxon::FlacStream;
    use hound::{WavSpec, WavWriter};

    let arg = env::args().nth(1).unwrap();
    let fname = path::Path::new(&arg);
    let input = fs::File::open(fname).unwrap();
    let mut reader = io::BufReader::new(input);
    let mut stream = FlacStream::new(&mut reader).unwrap();
    let n_samples = stream.streaminfo().n_samples.unwrap();

    let spec = WavSpec {
        // TODO: naming is inconsistent between Hound and Claxon.
        // TODO: u8 for n_channels, is that weird? Would u32 be better?
        channels: stream.streaminfo().n_channels as u16,
        sample_rate: stream.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: stream.streaminfo().bits_per_sample as u16
    };
    let fname_wav = fname.with_extension("wav");
    let mut output = WavWriter::create(fname_wav, spec).unwrap();

    let mut blocks = stream.blocks::<i32>();
    let mut sample = 0u64;
    let mut i = 0u64;

    while sample < n_samples {
        let block = blocks.read_next().unwrap();
        let left = block.channel(0);
        let right = block.channel(1);
        for (&l, &r) in left.iter().zip(right.iter()) {
            output.write_sample(l).ok().expect("failed to write sample");
            output.write_sample(r).ok().expect("failed to write sample");
        }
        sample = sample + block.len() as u64;
        i = i + 1;
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra_lapack;
extern crate nalgebra as na;
extern crate num;

use nalgebra_lapack::{HasSVD, HasEigensystem};

use na::{DMat,DVec,Norm,ColSlice,Iterable};
use num::complex::Complex;

#[test]
fn test_svd_wikipedia() {

  // Example from https://en.wikipedia.org/wiki/Singular_value_decomposition#Example

  let m = DMat::from_row_vec(4,5,&[
      1.0,   0.0,  0.0,   0.0,  2.0,
      0.0,   0.0,  3.0,   0.0,  0.0,
      0.0,   0.0,  0.0,   0.0,  0.0,
      0.0,   4.0,  0.0,   0.0,  0.0]);

  let (u,s,vt) = m.svd().unwrap();

  let mut expected_u: DMat<f64> = DMat::new_zeros( 4, 4);
  expected_u[(0,2)] =  1.0;
  expected_u[(1,1)] =  1.0;
  expected_u[(2,3)] = -1.0;
  expected_u[(3,0)] =  1.0;

  assert_eq!(u.nrows(),  expected_u.nrows());
  assert_eq!(u.ncols(),  expected_u.ncols());
  assert_eq!(u.as_vec(), expected_u.as_vec());

  let mut expected_s: DVec<f64> = DVec::from_elem( 4, 0.0);
  expected_s[0] = 4.0;
  expected_s[1] = 3.0;
  expected_s[2] = 5.0_f64.sqrt();

  assert_eq!(s.len(),  expected_s.len());
  assert_eq!(s.as_slice(), expected_s.as_slice());

  let mut expected_vt: DMat<f64> = DMat::new_zeros( 5, 5);
  expected_vt[(0,1)] =   1.0;
  expected_vt[(1,2)] =   1.0;
  expected_vt[(1,2)] =   1.0;
  expected_vt[(2,0)] =   0.2_f64.sqrt();
  expected_vt[(2,4)] =   0.8_f64.sqrt();
  expected_vt[(3,3)] =   1.0;
  expected_vt[(4,0)] = -(0.8_f64.sqrt());
  expected_vt[(4,4)] =   0.2_f64.sqrt();

  assert_eq!(vt.nrows(),  expected_vt.nrows());
  assert_eq!(vt.ncols(),  expected_vt.ncols());
  assert!(na::approx_eq(&vt, &expected_vt));
}

#[test]
fn test_svd_recomposition() {
  // The actual matrix contents and size should not matter.
  let m = DMat::from_row_vec(3,5,&[
      -1.01,   0.86,  -4.60,   3.31,  -4.81,
       3.98,   0.53,  -7.04,   5.29,   3.55,
       3.30,   8.26,  -3.89,   8.20,  -1.51]);
  let expected_m = m.clone(); // copy since original is moved into svd()
  let (u,s,vt) = m.svd().unwrap();

  let mut full_s = DMat::new_zeros( u.nrows(), vt.nrows() );
  for i in 0..s.len() {
    full_s[(i,i)] = s[i];
  }
  let actual_m = u*(full_s*vt);

  assert!(na::approx_eq(&actual_m, &expected_m));
}

#[test]
fn test_svd_recomposition_complex() {

  fn real_only_mat(u: DMat<Complex<f64>>) -> DMat<f64> {
      DMat::from_col_vec(u.nrows(),u.ncols(),&u.as_vec().iter().map( |c| {assert!(c.im==0.0); c.re}).collect::<Vec<_>>())
  }

  // The actual matrix contents and size should not matter.
  let mr = DMat::from_row_vec(3,5,&[
          -1.01,   0.86,  -4.60,   3.31,  -4.81,
           3.98,   0.53,  -7.04,   5.29,   3.55,
           3.30,   8.26,  -3.89,   8.20,  -1.51]);
  let expected_m = mr.clone(); // copy since original is moved into svd()
  let m: DMat<Complex<f64>> = DMat::from_col_vec(mr.nrows(),mr.ncols(),
    &mr.as_vec().iter().map( |re| {Complex{ re: *re, im: 0.0}}).collect::<Vec<_>>());

  let (uc,s,vtc) = m.svd().unwrap();
  let u = real_only_mat(uc);
  let vt = real_only_mat(vtc);

  let mut full_s = DMat::new_zeros( u.nrows(), vt.nrows() );
  for i in 0..s.len() {
    full_s[(i,i)] = s[i];
  }
  let actual_m = u*(full_s*vt);

  assert!(na::approx_eq(&actual_m, &expected_m));
}

fn real_only(a: &DVec<Complex<f64>> ) -> DVec<f64> {
    let v: Vec<_> = a.iter().map(|cmplx| {assert!(cmplx.im==0.0); cmplx.re}).collect();
    DVec{at:v}
}

fn na_position(a: &DVec<f64>, val: f64, eps: f64) -> Option<usize> {
    a.at.iter().position(|x| (*x-val).abs() < eps )
}

#[test]
fn test_eigenvalues_wikipedia_triangular() {

    // Based on example at
    // https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Triangular_matrices

    let n = 3;
    let mat = DMat::from_row_vec(n,n,&[
           1.0, 0.0, 0.0,
           1.0, 2.0, 0.0,
           2.0, 3.0, 3.0]);
    let (eigen_values, eigen_vectors) = mat.eigensystem().unwrap();

    assert!( eigen_values.len() == n);
    let ev = real_only(&eigen_values);
    let eps = 1e-16;

    // Check for eigvenvalue of 1.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev,1.0,eps) {
        let expected = DVec{at:vec![1.0, -1.0, 0.5]}.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i,0,n));
        assert!(na::approx_eq( &expected, &actual ));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 2.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev,2.0,eps) {
        let expected = DVec{at:vec![0.0, 1.0, -3.0]}.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i,0,n)).normalize();
        assert!(na::approx_eq( &expected, &actual ));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 3.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev,3.0,eps) {
        let expected = DVec{at:vec![0.0, 0.0, 1.0]}.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i,0,n)).normalize();
        assert!(na::approx_eq( &expected, &actual ));
    } else {
        panic!("expected value not found");
    }

}
<commit_msg>rustfmt<commit_after>extern crate nalgebra_lapack;
extern crate nalgebra as na;
extern crate num;

use nalgebra_lapack::{HasSVD, HasEigensystem};

use na::{DMat, DVec, Norm, ColSlice, Iterable};
use num::complex::Complex;

#[test]
fn test_svd_wikipedia() {

    // Example from https://en.wikipedia.org/wiki/Singular_value_decomposition#Example

    let m = DMat::from_row_vec(4,
                               5,
                               &[1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0]);

    let (u, s, vt) = m.svd().unwrap();

    let mut expected_u: DMat<f64> = DMat::new_zeros(4, 4);
    expected_u[(0, 2)] = 1.0;
    expected_u[(1, 1)] = 1.0;
    expected_u[(2, 3)] = -1.0;
    expected_u[(3, 0)] = 1.0;

    assert_eq!(u.nrows(), expected_u.nrows());
    assert_eq!(u.ncols(), expected_u.ncols());
    assert_eq!(u.as_vec(), expected_u.as_vec());

    let mut expected_s: DVec<f64> = DVec::from_elem(4, 0.0);
    expected_s[0] = 4.0;
    expected_s[1] = 3.0;
    expected_s[2] = 5.0_f64.sqrt();

    assert_eq!(s.len(), expected_s.len());
    assert_eq!(s.as_slice(), expected_s.as_slice());

    let mut expected_vt: DMat<f64> = DMat::new_zeros(5, 5);
    expected_vt[(0, 1)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(1, 2)] = 1.0;
    expected_vt[(2, 0)] = 0.2_f64.sqrt();
    expected_vt[(2, 4)] = 0.8_f64.sqrt();
    expected_vt[(3, 3)] = 1.0;
    expected_vt[(4, 0)] = -(0.8_f64.sqrt());
    expected_vt[(4, 4)] = 0.2_f64.sqrt();

    assert_eq!(vt.nrows(), expected_vt.nrows());
    assert_eq!(vt.ncols(), expected_vt.ncols());
    assert!(na::approx_eq(&vt, &expected_vt));
}

#[test]
fn test_svd_recomposition() {
    // The actual matrix contents and size should not matter.
    let m = DMat::from_row_vec(3,
                               5,
                               &[-1.01, 0.86, -4.60, 3.31, -4.81, 3.98, 0.53, -7.04, 5.29, 3.55,
                                 3.30, 8.26, -3.89, 8.20, -1.51]);
    let expected_m = m.clone(); // copy since original is moved into svd()
    let (u, s, vt) = m.svd().unwrap();

    let mut full_s = DMat::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

#[test]
fn test_svd_recomposition_complex() {

    fn real_only_mat(u: DMat<Complex<f64>>) -> DMat<f64> {
        DMat::from_col_vec(u.nrows(),
                           u.ncols(),
                           &u.as_vec()
                               .iter()
                               .map(|c| {
                                   assert!(c.im == 0.0);
                                   c.re
                               })
                               .collect::<Vec<_>>())
    }

    // The actual matrix contents and size should not matter.
    let mr = DMat::from_row_vec(3,
                                5,
                                &[-1.01, 0.86, -4.60, 3.31, -4.81, 3.98, 0.53, -7.04, 5.29, 3.55,
                                  3.30, 8.26, -3.89, 8.20, -1.51]);
    let expected_m = mr.clone(); // copy since original is moved into svd()
    let m: DMat<Complex<f64>> = DMat::from_col_vec(mr.nrows(),
                                                   mr.ncols(),
                                                   &mr.as_vec()
                                                       .iter()
                                                       .map(|re| Complex { re: *re, im: 0.0 })
                                                       .collect::<Vec<_>>());

    let (uc, s, vtc) = m.svd().unwrap();
    let u = real_only_mat(uc);
    let vt = real_only_mat(vtc);

    let mut full_s = DMat::new_zeros(u.nrows(), vt.nrows());
    for i in 0..s.len() {
        full_s[(i, i)] = s[i];
    }
    let actual_m = u * (full_s * vt);

    assert!(na::approx_eq(&actual_m, &expected_m));
}

fn real_only(a: &DVec<Complex<f64>>) -> DVec<f64> {
    let v: Vec<_> = a.iter()
        .map(|cmplx| {
            assert!(cmplx.im == 0.0);
            cmplx.re
        })
        .collect();
    DVec { at: v }
}

fn na_position(a: &DVec<f64>, val: f64, eps: f64) -> Option<usize> {
    a.at.iter().position(|x| (*x - val).abs() < eps)
}

#[test]
fn test_eigenvalues_wikipedia_triangular() {

    // Based on example at
    // https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Triangular_matrices

    let n = 3;
    let mat = DMat::from_row_vec(n, n, &[1.0, 0.0, 0.0, 1.0, 2.0, 0.0, 2.0, 3.0, 3.0]);
    let (eigen_values, eigen_vectors) = mat.eigensystem().unwrap();

    assert!(eigen_values.len() == n);
    let ev = real_only(&eigen_values);
    let eps = 1e-16;

    // Check for eigvenvalue of 1.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 1.0, eps) {
        let expected = DVec { at: vec![1.0, -1.0, 0.5] }.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i, 0, n));
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 2.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 2.0, eps) {
        let expected = DVec { at: vec![0.0, 1.0, -3.0] }.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

    // Check for eigvenvalue of 3.0 and corresponding eigenvector.
    if let Some(i) = na_position(&ev, 3.0, eps) {
        let expected = DVec { at: vec![0.0, 0.0, 1.0] }.normalize();
        let actual = real_only(&eigen_vectors.col_slice(i, 0, n)).normalize();
        assert!(na::approx_eq(&expected, &actual));
    } else {
        panic!("expected value not found");
    }

}
<|endoftext|>


<commit_before>extern crate sorting;

/// Verify order of input vector as sorted by indices.
///
/// # Details
///
/// This function takes as arguments a vector of data and a vector representing the indices of the
/// first vector making it sorted.
///
/// The elements of the sorted vector are compared to the next ones to make sure they are less
/// or equal.
///
/// # Panics
///
/// The sorting of the data vector is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// let sorted_indices: Vec<usize> = vec![3, 1, 2, 0];
/// verify_sorting(&data, &sorted_indices);
/// ```
///
fn verify_sorting<T: PartialOrd>(array: &Vec<T>, sorted_indices: &Vec<usize>) {
    let n = array.len();
    assert_eq!(n , sorted_indices.len());

    if !array.is_empty() {
        for i in 0..n-1 {
            assert!(array[sorted_indices[i]] <= array[sorted_indices[i+1]]);
        }
    }
}

/// Call the specified sorting function on an empty vector of specific type.
///
/// # Details
///
/// This function takes as arguments a pointer to a sorting function acting and call
/// it on an empty vector of type T. The call should succeed and the index vector should
/// be empty as well.
///
/// # Panics
///
/// The emptiness of the sorted list is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
/// ```
///
fn test_empty_vec<T: PartialOrd>(sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let to_sort: Vec<T> = vec![];
    let sorted_indices = sorting_fct(&to_sort);
    assert_eq!(sorted_indices, vec![]);
    assert!(sorted_indices.is_empty());
}

/// Validate against empty vector (i8).
#[test]
fn simple_insertion_empty_vec_i8() {
    test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i16() {
    test_empty_vec::<i16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i32() {
    test_empty_vec::<i32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i64).
#[test]
fn simple_insertion_empty_vec_i64() {
    test_empty_vec::<i64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (u8).
#[test]
fn simple_insertion_empty_vec_u8() {
    test_empty_vec::<u8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u16() {
    test_empty_vec::<u16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u32() {
    test_empty_vec::<u32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u64).
#[test]
fn simple_insertion_empty_vec_u64() {
    test_empty_vec::<u64>(sorting::simplesorts::insertion::sort);
}

/// Validate a vector of double precision values.
#[test]
fn simple_insertion_vec_f64() {
    let to_sort: Vec<f64> = vec![6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                 3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];

    let sorted_indices = sorting::simplesorts::insertion::sort(&to_sort);

    verify_sorting(&to_sort, &sorted_indices);

    assert_eq!(sorted_indices, vec![3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12]);
}
<commit_msg>Implement generic validation for floats.<commit_after>extern crate sorting;

/// Verify order of input vector as sorted by indices.
///
/// # Details
///
/// This function takes as arguments a vector of data and a vector representing the indices of the
/// first vector making it sorted.
///
/// The elements of the sorted vector are compared to the next ones to make sure they are less
/// or equal.
///
/// # Panics
///
/// The sorting of the data vector is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// let data: Vec<i32> = vec![4, 2, 3, 1];
/// let sorted_indices: Vec<usize> = vec![3, 1, 2, 0];
/// verify_sorting(&data, &sorted_indices);
/// ```
///
fn verify_sorting<T: PartialOrd>(array: &Vec<T>, sorted_indices: &Vec<usize>) {
    let n = array.len();
    assert_eq!(n , sorted_indices.len());

    if !array.is_empty() {
        for i in 0..n-1 {
            assert!(array[sorted_indices[i]] <= array[sorted_indices[i+1]]);
        }
    }
}

/// Call the specified sorting function on an empty vector of specific type.
///
/// # Details
///
/// This function takes as arguments a pointer to a sorting function acting and call
/// it on an empty vector of type T. The call should succeed and the index vector should
/// be empty as well.
///
/// # Panics
///
/// The emptiness of the sorted list is enforced using `assert!()`.
///
/// # Examples
///
/// ```
/// test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
/// ```
///
fn test_empty_vec<T: PartialOrd>(sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let to_sort: Vec<T> = vec![];
    let sorted_indices = sorting_fct(&to_sort);
    assert_eq!(sorted_indices, vec![]);
    assert!(sorted_indices.is_empty());
}

fn test_sort_vec_float<T: PartialOrd>(to_sort: &Vec<T>, expected_indices: &Vec<usize>,
                                      sorting_fct: fn(&Vec<T>) -> Vec<usize>) {
    let sorted_indices = sorting_fct(&to_sort);

    verify_sorting(&to_sort, &sorted_indices);

    assert_eq!(sorted_indices.len(), expected_indices.len());

    for i in 0..to_sort.len() {
        assert_eq!(sorted_indices[i], expected_indices[i]);
    }
}

/// Validate against empty vector (i8).
#[test]
fn simple_insertion_empty_vec_i8() {
    test_empty_vec::<i8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i16() {
    test_empty_vec::<i16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i32).
#[test]
fn simple_insertion_empty_vec_i32() {
    test_empty_vec::<i32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (i64).
#[test]
fn simple_insertion_empty_vec_i64() {
    test_empty_vec::<i64>(sorting::simplesorts::insertion::sort);
}

/// Validate against empty vector (u8).
#[test]
fn simple_insertion_empty_vec_u8() {
    test_empty_vec::<u8>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u16() {
    test_empty_vec::<u16>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u32).
#[test]
fn simple_insertion_empty_vec_u32() {
    test_empty_vec::<u32>(sorting::simplesorts::insertion::sort);
}
/// Validate against empty vector (u64).
#[test]
fn simple_insertion_empty_vec_u64() {
    test_empty_vec::<u64>(sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of single precision values (f32).
#[test]
fn simple_insertion_vec_f32() {
    let to_sort: Vec<f32> = vec![6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                 3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];

    let known_sorted_indices = vec![3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

    test_sort_vec_float::<f32>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}

/// Validate sorting a vector of double precision values (f64).
#[test]
fn simple_insertion_vec_f64() {
    let to_sort: Vec<f64> = vec![6.0,   5.0,  3.0,  1.0,  2.4, 4.0, 10.0, 7.0,
                                 3.42, 32.2, 44.2, 56.3, 67.9, 3.2, 44.2, 2.0];

    let known_sorted_indices = vec![3, 15, 4, 2, 13, 8, 5, 1, 0, 7, 6, 9, 10, 14, 11, 12];

    test_sort_vec_float::<f64>(&to_sort, &known_sorted_indices,
                               sorting::simplesorts::insertion::sort);
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 50, 50, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            println!("{}", res.text().unwrap());
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<commit_msg>Update tests for new version<commit_after>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 50, 51, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            println!("{}", res.text().unwrap());
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<|endoftext|>


<commit_before>extern crate jsrs_parser;

use jsrs_parser::lalr::parse_Stmt;
use std::io::{self, Write};

fn main() {
    let stdin = io::stdin();
    let mut stdout = io::stdout();

    loop {
        print!(">> ");
        stdout.flush().unwrap();
        let mut input = String::new();
        stdin.read_line(&mut input).unwrap();

        if &input == ".exit\n" {
            return;
        }

        let stmt = match parse_Stmt(&input) {
            Ok(s) => s,
            _ => {
                println!("Error: failed to parse");
                continue
            }
        };

        println!("=> {:?}", stmt);
    }
}
<commit_msg>use stderr for the error messages<commit_after>extern crate jsrs_parser;

use jsrs_parser::lalr::parse_Stmt;
use std::io::{self, Write};

fn main() {
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    loop {
        print!(">> ");
        stdout.flush().unwrap();
        let mut input = String::new();
        stdin.read_line(&mut input).unwrap();

        if &input == ".exit\n" {
            return;
        }

        let stmt = match parse_Stmt(&input) {
            Ok(s) => s,
            _ => {
                writeln!(stderr, "Error: failed to parse").unwrap();
                continue
            }
        };

        println!("=> {:?}", stmt);
    }
}
<|endoftext|>


<commit_before>use crate::get_book_dir;
use clap::{App, ArgMatches, SubCommand};
use mdbook::errors::*;
use mdbook::MDBook;
use std::fs;

// Create clap subcommand arguments
pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name("clean")
        .about("Deletes a built book")
        .arg_from_usage(
            "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
             Relative paths are interpreted relative to the book's root directory.{n}\
             Running this command deletes this directory.{n}\
             If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
        )
        .arg_from_usage(
            "[dir] 'Root directory for the book{n}\
             (Defaults to the Current Directory when omitted)'",
        )
}

// Clean command implementation
pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir)?;

    let dir_to_remove = match args.value_of("dest-dir") {
        Some(dest_dir) => dest_dir.into(),
        None => book.root.join(&book.config.build.build_dir),
    };
    fs::remove_dir_all(&dir_to_remove).chain_err(|| "Unable to remove the build directory")?;

    Ok(())
}
<commit_msg>Fix (command:clean): removes error message 'dir not found' if 'clean' is run multiple times (uses existing path variable)<commit_after>use crate::get_book_dir;
use clap::{App, ArgMatches, SubCommand};
use mdbook::errors::*;
use mdbook::MDBook;
use std::fs;

// Create clap subcommand arguments
pub fn make_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name("clean")
        .about("Deletes a built book")
        .arg_from_usage(
            "-d, --dest-dir=[dest-dir] 'Output directory for the book{n}\
             Relative paths are interpreted relative to the book's root directory.{n}\
             Running this command deletes this directory.{n}\
             If omitted, mdBook uses build.build-dir from book.toml or defaults to `./book`.'",
        )
        .arg_from_usage(
            "[dir] 'Root directory for the book{n}\
             (Defaults to the Current Directory when omitted)'",
        )
}

// Clean command implementation
pub fn execute(args: &ArgMatches) -> mdbook::errors::Result<()> {
    let book_dir = get_book_dir(args);
    let book = MDBook::load(&book_dir)?;

    let dir_to_remove = match args.value_of("dest-dir") {
        Some(dest_dir) => dest_dir.into(),
        None => book.root.join(&book.config.build.build_dir),
    };

    if dir_to_remove.exists() {
        fs::remove_dir_all(&dir_to_remove).chain_err(|| "Unable to remove the build directory")?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use scoped_map::ScopedMap;
use ast::*;
use interner::*;

#[deriving(Clone, Eq, PartialEq, Show)]
pub struct TcIdent {
    pub typ: TcType,
    pub name: InternedStr
}
impl TcIdent {
    pub fn id(&self) -> &InternedStr {
        &self.name
    }
}

impl Str for TcIdent {
    fn as_slice(&self) -> &str {
        self.name.as_slice()
    }
}

type TcType = Type<InternedStr>;

#[deriving(Show)]
enum TypeError {
    UndefinedVariable(InternedStr),
    NotAFunction(TcType),
    WrongNumberOfArguments(uint, uint),
    TypeMismatch(TcType, TcType),
    UndefinedStruct(InternedStr),
    UndefinedField(InternedStr, InternedStr),
    TypeError(&'static str)
}

type TcResult = Result<TcType, TypeError>;

fn find_type<'a>(module: &'a Module<TcIdent>, name: &InternedStr) -> Option<TcType> {
    module.functions.iter()
        .find(|f| f.name.id() == name)
        .map(|f| FunctionType(f.arguments.iter().map(|field| field.typ.clone()).collect(), box f.return_type.clone()))
        .or_else(|| module.structs.iter()
            .find(|s| s.name.id() == name)
            .map(|s| s.name.typ.clone())
        )
}

pub struct Typecheck<'a> {
    module: HashMap<InternedStr, TcType>,
    structs: HashMap<InternedStr, Vec<(InternedStr, TcType)>>,
    stack: ScopedMap<InternedStr, TcType>
}

impl <'a> Typecheck<'a> {

    pub fn new() -> Typecheck<'a> {
        Typecheck {
            module: HashMap::new(),
            structs: HashMap::new(),
            stack: ScopedMap::new()
        }
    }

    fn find(&self, id: &InternedStr) -> TcResult {
        self.stack.find(id)
            .or_else(|| self.module.find(id))
            .map(|t| t.clone())
            .map(Ok)
            .unwrap_or_else(|| Err(UndefinedVariable(id.clone())))
    }

    fn find_enum(&self, id: &InternedStr) -> Result<(), TypeError> {
        Ok(())
    }

    fn find_struct(&self, id: &InternedStr) -> Result<&Vec<(InternedStr, TcType)>, TypeError> {
        self.structs.find(id)
            .map(|s| Ok(s))
            .unwrap_or_else(|| Err(UndefinedStruct(id.clone())))
    }

    fn stack_var(&mut self, id: InternedStr, typ: TcType) {
        self.stack.insert(id, typ);
    }

    pub fn typecheck_module(&mut self, module: &mut Module<TcIdent>) -> Result<(), TypeError> {

        for f in module.functions.mut_iter() {
            f.name.typ = FunctionType(f.arguments.iter().map(|f| f.typ.clone()).collect(), box f.return_type.clone());
            self.module.insert(f.name.name, f.name.typ.clone());
        }
        for s in module.structs.mut_iter() {
            let fields = s.fields.iter().map(|f| (f.name, f.typ.clone())).collect();
            self.structs.insert(s.name.name, fields);

            let args = s.fields.iter().map(|f| f.typ.clone()).collect();
            s.name.typ = FunctionType(args, box Type(s.name.name));
            self.module.insert(s.name.name, s.name.typ.clone());
        }
        for e in module.enums.iter() {
            for ctor in e.constructors.iter() {
                let typ = FunctionType(ctor.arguments.clone(), box Type(e.name.name));
                self.module.insert(ctor.name.name, typ);
            }
        }
        for f in module.functions.mut_iter() {
            try!(self.typecheck_function(f));
        }
        Ok(())
    }

    fn typecheck_function(&mut self, function: &mut Function<TcIdent>) -> Result<(), TypeError> {
        self.stack.clear();
        for arg in function.arguments.iter() {
            self.stack_var(arg.name.clone(), arg.typ.clone());
        }
        let return_type = try!(self.typecheck(&mut function.expression));
        self.unify(&function.return_type, return_type)
            .map(|_| ())
    }

    fn typecheck(&mut self, expr: &mut Expr<TcIdent>) -> TcResult {
        match *expr {
            Identifier(ref mut id) => {
                id.typ = try!(self.find(id.id()));
                Ok(id.typ.clone())
            }
            Literal(ref lit) => {
                Ok(match *lit {
                    Integer(_) => int_type.clone(),
                    Float(_) => float_type.clone(),
                    String(_) => string_type.clone(),
                    Bool(_) => bool_type.clone()
                })
            }
            Call(ref mut func, ref mut args) => {
                let func_type = try!(self.typecheck(&mut**func));
                match func_type {
                    FunctionType(arg_types, return_type) => {
                        if arg_types.len() != args.len() {
                            return Err(WrongNumberOfArguments(arg_types.len(), args.len()));
                        }
                        for i in range(0, arg_types.len()) {
                            let actual = try!(self.typecheck(args.get_mut(i)));
                            try!(self.unify(&arg_types[i], actual));
                        }
                        Ok(*return_type)
                    }
                    t => Err(NotAFunction(t))
                }
            }
            IfElse(ref mut pred, ref mut if_true, ref mut if_false) => {
                let pred_type = try!(self.typecheck(&mut**pred));
                self.unify(&bool_type, pred_type);
                let true_type = try!(self.typecheck(&mut**if_true));
                let false_type = try!(self.typecheck(&mut**if_false));
                self.unify(&true_type, false_type)
            }
            While(ref mut pred, ref mut expr) => {
                let pred_type = try!(self.typecheck(&mut **pred));
                try!(self.unify(&bool_type, pred_type));
                self.typecheck(&mut**expr)
                    .map(|_| unit_type.clone())
            }
            BinOp(ref mut lhs, ref mut op, ref mut rhs) => {
                let lhs_type = try!(self.typecheck(&mut**lhs));
                let rhs_type = try!(self.typecheck(&mut**rhs));
                try!(self.unify(&lhs_type, rhs_type.clone()));
                match op.as_slice() {
                    "+" | "-" | "*" => {
                        if lhs_type == int_type || lhs_type == float_type {
                            Ok(lhs_type)
                        }
                        else {
                            return Err(TypeError("Expected numbers in binop"))
                        }
                    }
                    "<" | ">" | "<=" | ">=" => Ok(bool_type.clone()),
                    _ => Err(UndefinedVariable(op.name.clone()))
                }
            }
            Block(ref mut exprs) => {
                self.stack.enter_scope();
                let mut typ = unit_type.clone();
                for expr in exprs.mut_iter() {
                    typ = try!(self.typecheck(expr));
                }
                self.stack.exit_scope();
                Ok(typ)
            }
            Match(ref mut expr, ref mut alts) => {
                let typ = try!(self.typecheck(&mut**expr));
                self.stack.enter_scope();
                try!(self.typecheck_pattern(&mut alts.get_mut(0).pattern, typ.clone()));
                let alt1_type = try!(self.typecheck(&mut alts.get_mut(0).expression));
                self.stack.exit_scope();

                for alt in alts.mut_iter().skip(1) {
                    self.stack.enter_scope();
                    try!(self.typecheck_pattern(&alt.pattern, typ.clone()));
                    let alt_type = try!(self.typecheck(&mut alt.expression));
                    self.stack.exit_scope();
                    try!(self.unify(&alt1_type, alt_type));
                }
                Ok(alt1_type)
            }
            Let(ref mut id, ref mut expr) => {
                id.typ = try!(self.typecheck(&mut **expr));
                self.stack_var(id.name.clone(), id.typ.clone());
                Ok(unit_type.clone())
            }
            Assign(ref mut lhs, ref mut rhs) => {
                let rhs_type = try!(self.typecheck(&mut **rhs));
                let lhs_type = try!(self.typecheck(&mut **lhs));
                self.unify(&lhs_type, rhs_type)
            }
            FieldAccess(ref mut expr, ref mut id) => {
                let typ = try!(self.typecheck(&mut **expr));
                match typ {
                    Type(ref struct_id) => {
                        let fields = try!(self.find_struct(struct_id));
                        id.typ = try!(fields.iter()
                            .find(|& &(ref name, _)| *name == id.name)
                            .map(|&(_, ref t)| Ok(t.clone()))
                            .unwrap_or_else(|| Err(UndefinedField(struct_id.clone(), id.name.clone()))));
                        Ok(id.typ.clone())
                    }
                    FunctionType(..) => Err(TypeError("Field access on function")),
                    LiteralType(..) => Err(TypeError("Field acces on primitive"))
                }
            }
        }
    }

    fn typecheck_pattern(&mut self, pattern: &Pattern<TcIdent>, match_type: TcType) -> Result<(), TypeError> {
        match *pattern {
            ConstructorPattern(ref name, _) => {
                let ctor_type = try!(self.find(name.id()));
                match ctor_type {
                    FunctionType(_, ref return_type) => {
                        self.unify(&**return_type, match_type)
                            .map(|_| ())
                    }
                    _ => self.unify(&ctor_type, match_type)
                            .map(|_| ())
                }
            }
            IdentifierPattern(ref id) => {
                self.stack_var(id.id().clone(), match_type);
                Ok(())
            }
        }
    }

    fn unify(&self, expected: &TcType, actual: TcType) -> TcResult {
        if *expected == actual {
            Ok(actual)
        }
        else {
            Err(TypeMismatch(expected.clone(), actual))
        }
    }
}

pub trait Typed {
    fn type_of(&self) -> &Type<InternedStr>;
}
impl Typed for TcIdent {
    fn type_of(&self) -> &Type<InternedStr> {
        &self.typ
    }
}
impl <Id: Typed + Str> Typed for Expr<Id> {
    fn type_of(&self) -> &Type<InternedStr> {
        match *self {
            Identifier(ref id) => id.type_of(),
            Literal(ref lit) => {
                match *lit {
                    Integer(_) => &int_type,
                    Float(_) => &float_type,
                    String(_) => &string_type,
                    Bool(_) => &bool_type
                }
            }
            IfElse(_, ref arm, _) => arm.type_of(),
            Block(ref exprs) => {
                if exprs.len() == 0 {
                    &unit_type
                }
                else {
                    exprs.last().unwrap().type_of()
                }
            }
            BinOp(ref lhs, ref op, _) => {
                match op.as_slice() {
                    "+" | "-" | "*" => lhs.type_of(),
                    "<" | ">" | "<=" | ">=" => &bool_type,
                    _ => fail!()
                }
            }
            Let(..) | While(..) | Assign(..) => &unit_type,
            Call(ref func, _) => {
                match func.type_of() {
                    &FunctionType(_, ref return_type) => &**return_type,
                    _ => fail!()
                }
            }
            Match(_, ref alts) => alts[0].expression.type_of(),
            FieldAccess(_, ref id) => id.type_of()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::TcIdent;
    use ast::*;
    use parser::*;
    use interner::InternedStr;

    pub fn parse<T>(s: &str, f: |&mut Parser<TcIdent>|:'static -> ParseResult<T>) -> T {
        use std::io::BufReader;
        let mut buffer = BufReader::new(s.as_bytes());
        let mut parser = Parser::new(&mut buffer, |s| TcIdent { typ: unit_type.clone(), name: s });
        f(&mut parser)
            .unwrap_or_else(|err| fail!(err))
    }

    #[test]
    fn while_() {
        let text = "fn main() { let x = 2; while x < 10 { x } }";
        let mut module = parse(text, |p| p.module());
        let mut tc = Typecheck::new();
        tc.typecheck_module(&mut module)
            .unwrap_or_else(|err| fail!(err))

    }
    #[test]
    fn enums() {
        let text =
r"
enum AB {
    A(int),
    B(float)
}
fn main() -> int {
    match A(1) {
        A(x) => { x }
        B(x) => { 0 }
    }
}";
        let mut module = parse(text, |p| p.module());
        let mut tc = Typecheck::new();
        tc.typecheck_module(&mut module)
            .unwrap_or_else(|err| fail!("{}", err))

    }
}
<commit_msg>Added typechecking for match expressions<commit_after>use std::collections::HashMap;
use scoped_map::ScopedMap;
use ast::*;
use interner::*;

#[deriving(Clone, Eq, PartialEq, Show)]
pub struct TcIdent {
    pub typ: TcType,
    pub name: InternedStr
}
impl TcIdent {
    pub fn id(&self) -> &InternedStr {
        &self.name
    }
}

impl Str for TcIdent {
    fn as_slice(&self) -> &str {
        self.name.as_slice()
    }
}

type TcType = Type<InternedStr>;

#[deriving(Show)]
enum TypeError {
    UndefinedVariable(InternedStr),
    NotAFunction(TcType),
    WrongNumberOfArguments(uint, uint),
    TypeMismatch(TcType, TcType),
    UndefinedStruct(InternedStr),
    UndefinedField(InternedStr, InternedStr),
    TypeError(&'static str)
}

type TcResult = Result<TcType, TypeError>;

fn find_type<'a>(module: &'a Module<TcIdent>, name: &InternedStr) -> Option<TcType> {
    module.functions.iter()
        .find(|f| f.name.id() == name)
        .map(|f| FunctionType(f.arguments.iter().map(|field| field.typ.clone()).collect(), box f.return_type.clone()))
        .or_else(|| module.structs.iter()
            .find(|s| s.name.id() == name)
            .map(|s| s.name.typ.clone())
        )
}

enum TypeInfo {
    Struct(Vec<(InternedStr, TcType)>),
    Enum(Enum<TcIdent>)
}

pub struct Typecheck<'a> {
    module: HashMap<InternedStr, TcType>,
    type_infos: HashMap<InternedStr, TypeInfo>,
    stack: ScopedMap<InternedStr, TcType>
}

impl <'a> Typecheck<'a> {

    pub fn new() -> Typecheck<'a> {
        Typecheck {
            module: HashMap::new(),
            type_infos: HashMap::new(),
            stack: ScopedMap::new()
        }
    }

    fn find(&self, id: &InternedStr) -> TcResult {
        self.stack.find(id)
            .or_else(|| self.module.find(id))
            .map(|t| t.clone())
            .map(Ok)
            .unwrap_or_else(|| Err(UndefinedVariable(id.clone())))
    }

    fn find_enum(&self, id: &InternedStr) -> Result<(), TypeError> {
        Ok(())
    }

    fn find_type_info(&self, id: &InternedStr) -> Result<&TypeInfo, TypeError> {
        self.type_infos.find(id)
            .map(|s| Ok(s))
            .unwrap_or_else(|| Err(UndefinedStruct(id.clone())))
    }

    fn stack_var(&mut self, id: InternedStr, typ: TcType) {
        self.stack.insert(id, typ);
    }

    pub fn typecheck_module(&mut self, module: &mut Module<TcIdent>) -> Result<(), TypeError> {

        for f in module.functions.mut_iter() {
            f.name.typ = FunctionType(f.arguments.iter().map(|f| f.typ.clone()).collect(), box f.return_type.clone());
            self.module.insert(f.name.name, f.name.typ.clone());
        }
        for s in module.structs.mut_iter() {
            let fields = s.fields.iter().map(|f| (f.name, f.typ.clone())).collect();
            self.type_infos.insert(s.name.name, Struct(fields));

            let args = s.fields.iter().map(|f| f.typ.clone()).collect();
            s.name.typ = FunctionType(args, box Type(s.name.name));
            self.module.insert(s.name.name, s.name.typ.clone());
        }
        for e in module.enums.iter() {
            self.type_infos.insert(e.name.name, Enum(e.clone()));
            for ctor in e.constructors.iter() {
                let typ = FunctionType(ctor.arguments.clone(), box Type(e.name.name));
                self.module.insert(ctor.name.name, typ);
            }
        }
        for f in module.functions.mut_iter() {
            try!(self.typecheck_function(f));
        }
        Ok(())
    }

    fn typecheck_function(&mut self, function: &mut Function<TcIdent>) -> Result<(), TypeError> {
        self.stack.clear();
        for arg in function.arguments.iter() {
            self.stack_var(arg.name.clone(), arg.typ.clone());
        }
        let return_type = try!(self.typecheck(&mut function.expression));
        self.unify(&function.return_type, return_type)
            .map(|_| ())
    }

    fn typecheck(&mut self, expr: &mut Expr<TcIdent>) -> TcResult {
        match *expr {
            Identifier(ref mut id) => {
                id.typ = try!(self.find(id.id()));
                Ok(id.typ.clone())
            }
            Literal(ref lit) => {
                Ok(match *lit {
                    Integer(_) => int_type.clone(),
                    Float(_) => float_type.clone(),
                    String(_) => string_type.clone(),
                    Bool(_) => bool_type.clone()
                })
            }
            Call(ref mut func, ref mut args) => {
                let func_type = try!(self.typecheck(&mut**func));
                match func_type {
                    FunctionType(arg_types, return_type) => {
                        if arg_types.len() != args.len() {
                            return Err(WrongNumberOfArguments(arg_types.len(), args.len()));
                        }
                        for i in range(0, arg_types.len()) {
                            let actual = try!(self.typecheck(args.get_mut(i)));
                            try!(self.unify(&arg_types[i], actual));
                        }
                        Ok(*return_type)
                    }
                    t => Err(NotAFunction(t))
                }
            }
            IfElse(ref mut pred, ref mut if_true, ref mut if_false) => {
                let pred_type = try!(self.typecheck(&mut**pred));
                self.unify(&bool_type, pred_type);
                let true_type = try!(self.typecheck(&mut**if_true));
                let false_type = try!(self.typecheck(&mut**if_false));
                self.unify(&true_type, false_type)
            }
            While(ref mut pred, ref mut expr) => {
                let pred_type = try!(self.typecheck(&mut **pred));
                try!(self.unify(&bool_type, pred_type));
                self.typecheck(&mut**expr)
                    .map(|_| unit_type.clone())
            }
            BinOp(ref mut lhs, ref mut op, ref mut rhs) => {
                let lhs_type = try!(self.typecheck(&mut**lhs));
                let rhs_type = try!(self.typecheck(&mut**rhs));
                try!(self.unify(&lhs_type, rhs_type.clone()));
                match op.as_slice() {
                    "+" | "-" | "*" => {
                        if lhs_type == int_type || lhs_type == float_type {
                            Ok(lhs_type)
                        }
                        else {
                            return Err(TypeError("Expected numbers in binop"))
                        }
                    }
                    "<" | ">" | "<=" | ">=" => Ok(bool_type.clone()),
                    _ => Err(UndefinedVariable(op.name.clone()))
                }
            }
            Block(ref mut exprs) => {
                self.stack.enter_scope();
                let mut typ = unit_type.clone();
                for expr in exprs.mut_iter() {
                    typ = try!(self.typecheck(expr));
                }
                self.stack.exit_scope();
                Ok(typ)
            }
            Match(ref mut expr, ref mut alts) => {
                let typ = try!(self.typecheck(&mut**expr));
                self.stack.enter_scope();
                try!(self.typecheck_pattern(&mut alts.get_mut(0).pattern, typ.clone()));
                let alt1_type = try!(self.typecheck(&mut alts.get_mut(0).expression));
                self.stack.exit_scope();

                for alt in alts.mut_iter().skip(1) {
                    self.stack.enter_scope();
                    try!(self.typecheck_pattern(&mut alt.pattern, typ.clone()));
                    let alt_type = try!(self.typecheck(&mut alt.expression));
                    self.stack.exit_scope();
                    try!(self.unify(&alt1_type, alt_type));
                }
                Ok(alt1_type)
            }
            Let(ref mut id, ref mut expr) => {
                id.typ = try!(self.typecheck(&mut **expr));
                self.stack_var(id.name.clone(), id.typ.clone());
                Ok(unit_type.clone())
            }
            Assign(ref mut lhs, ref mut rhs) => {
                let rhs_type = try!(self.typecheck(&mut **rhs));
                let lhs_type = try!(self.typecheck(&mut **lhs));
                self.unify(&lhs_type, rhs_type)
            }
            FieldAccess(ref mut expr, ref mut id) => {
                let typ = try!(self.typecheck(&mut **expr));
                match typ {
                    Type(ref struct_id) => {
                        let type_info = try!(self.find_type_info(struct_id));
                        match *type_info {
                            Struct(ref fields) => {
                                id.typ = try!(fields.iter()
                                    .find(|& &(ref name, _)| *name == id.name)
                                    .map(|&(_, ref t)| Ok(t.clone()))
                                    .unwrap_or_else(|| Err(UndefinedField(struct_id.clone(), id.name.clone()))));
                                Ok(id.typ.clone())
                            }
                            Enum(_) => Err(TypeError("Field access on enum type"))
                        }
                    }
                    FunctionType(..) => Err(TypeError("Field access on function")),
                    LiteralType(..) => Err(TypeError("Field acces on primitive"))
                }
            }
        }
    }

    fn typecheck_pattern(&mut self, pattern: &mut Pattern<TcIdent>, match_type: TcType) -> Result<(), TypeError> {
        let typename = match match_type {
            Type(id) => id,
            _ => return Err(TypeError("Pattern matching only works on enums"))
        };
        match *pattern {
            ConstructorPattern(ref name, ref mut args) => {
                //Find the enum constructor and return the types for its arguments
                let argument_types: Vec<TcType> = match *try!(self.find_type_info(&typename)) {
                    Enum(ref e) => {
                        match e.constructors.iter().find(|ctor| ctor.name.id() == name.id()) {
                            Some(ctor) => ctor.arguments.iter().map(|t| t.clone()).collect(),
                            None => return Err(TypeError("Undefined constructor"))
                        }
                    }
                    Struct(..) => return Err(TypeError("Pattern match on struct"))
                };
                for (arg, typ) in args.iter().zip(argument_types.move_iter()) {
                    self.stack_var(arg.id().clone(), typ);
                }
                Ok(())
            }
            IdentifierPattern(ref id) => {
                self.stack_var(id.id().clone(), match_type);
                Ok(())
            }
        }
    }

    fn unify(&self, expected: &TcType, actual: TcType) -> TcResult {
        if *expected == actual {
            Ok(actual)
        }
        else {
            Err(TypeMismatch(expected.clone(), actual))
        }
    }
}

pub trait Typed {
    fn type_of(&self) -> &Type<InternedStr>;
}
impl Typed for TcIdent {
    fn type_of(&self) -> &Type<InternedStr> {
        &self.typ
    }
}
impl <Id: Typed + Str> Typed for Expr<Id> {
    fn type_of(&self) -> &Type<InternedStr> {
        match *self {
            Identifier(ref id) => id.type_of(),
            Literal(ref lit) => {
                match *lit {
                    Integer(_) => &int_type,
                    Float(_) => &float_type,
                    String(_) => &string_type,
                    Bool(_) => &bool_type
                }
            }
            IfElse(_, ref arm, _) => arm.type_of(),
            Block(ref exprs) => {
                if exprs.len() == 0 {
                    &unit_type
                }
                else {
                    exprs.last().unwrap().type_of()
                }
            }
            BinOp(ref lhs, ref op, _) => {
                match op.as_slice() {
                    "+" | "-" | "*" => lhs.type_of(),
                    "<" | ">" | "<=" | ">=" => &bool_type,
                    _ => fail!()
                }
            }
            Let(..) | While(..) | Assign(..) => &unit_type,
            Call(ref func, _) => {
                match func.type_of() {
                    &FunctionType(_, ref return_type) => &**return_type,
                    _ => fail!()
                }
            }
            Match(_, ref alts) => alts[0].expression.type_of(),
            FieldAccess(_, ref id) => id.type_of()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::TcIdent;
    use ast::*;
    use parser::*;
    use interner::InternedStr;

    pub fn parse<T>(s: &str, f: |&mut Parser<TcIdent>|:'static -> ParseResult<T>) -> T {
        use std::io::BufReader;
        let mut buffer = BufReader::new(s.as_bytes());
        let mut parser = Parser::new(&mut buffer, |s| TcIdent { typ: unit_type.clone(), name: s });
        f(&mut parser)
            .unwrap_or_else(|err| fail!(err))
    }

    #[test]
    fn while_() {
        let text = "fn main() { let x = 2; while x < 10 { x } }";
        let mut module = parse(text, |p| p.module());
        let mut tc = Typecheck::new();
        tc.typecheck_module(&mut module)
            .unwrap_or_else(|err| fail!(err))

    }
    #[test]
    fn enums() {
        let text =
r"
enum AB {
    A(int),
    B(float)
}
fn main() -> int {
    match A(1) {
        A(x) => { x }
        B(x) => { 0 }
    }
}";
        let mut module = parse(text, |p| p.module());
        let mut tc = Typecheck::new();
        tc.typecheck_module(&mut module)
            .unwrap_or_else(|err| fail!("{}", err))

    }
}
<|endoftext|>


<commit_before>use sync::{Arc, Mutex};
use super::super::error::{MyDriverError, InvalidPoolConstraints};
use super::{MyConn, MyOpts, Stmt, QueryResult};
use super::super::error::{MyResult};

struct MyInnerPool {
    opts: MyOpts,
    pool: Vec<MyConn>,
    min: uint,
    max: uint,
    count: uint
}

impl MyInnerPool {
    fn new(min: uint, max: uint, opts: MyOpts) -> MyResult<MyInnerPool> {
        if min > max || max == 0 {
            return Err(MyDriverError(InvalidPoolConstraints));
        }
        let mut pool = MyInnerPool {
            opts: opts,
            pool: Vec::with_capacity(max),
            max: max,
            min: min,
            count: 0
        };
        for _ in range(0, min) {
            try!(pool.new_conn());
        }
        Ok(pool)
    }
    fn new_conn(&mut self) -> MyResult<()> {
        match MyConn::new(self.opts.clone()) {
            Ok(conn) => {
                self.pool.push(conn);
                Ok(())
            },
            Err(err) => Err(err)
        }
    }
}

/// Pool which is holding mysql connections.
///
/// It will hold at least `min` connections and will create as many as `max`
/// connections.
///
/// ```
/// use mysql::conn::{MyOpts};
/// use std::default::{Default};
/// use mysql::conn::pool::{MyPool};
/// use mysql::value::{ToValue};
///
/// fn main() {
///     # let opts = MyOpts{user: Some("root".to_string()),
///     #                   pass: Some("password".to_string()),
///     #                   tcp_addr: Some("127.0.0.1".to_string()),
///     #                   tcp_port: 3307,
///     #                   ..Default::default()};
///     let pool = MyPool::new(opts);
///     assert!(pool.is_ok());
///     let pool = pool.unwrap();
///     for _ in range(0u, 100) {
///         let pool = pool.clone();
///         spawn(proc() {
///             let conn = pool.get_conn();
///             assert!(conn.is_ok());
///             let mut conn = conn.unwrap();
///             let result = conn.query("SELECT 1");
///             assert!(result.is_ok());
///             let mut result = result.unwrap();
///             assert_eq!(result.next(), Some(Ok(vec!["1".to_value()])));
///         });
///     }
/// }
/// ```
#[deriving(Clone)]
pub struct MyPool {
    pool: Arc<Mutex<MyInnerPool>>
}

impl MyPool {
    /// Creates new pool with `min = 10` and `max = 100`.
    pub fn new(opts: MyOpts) -> MyResult<MyPool> {
        MyPool::new_manual(10, 100, opts)
    }

    /// Same as `new` but you can set `min` and `max`.
    pub fn new_manual(min: uint, max: uint, opts: MyOpts) -> MyResult<MyPool> {
        let pool = try!(MyInnerPool::new(min, max, opts));
        Ok(MyPool{ pool: Arc::new(Mutex::new(pool)) })
    }

    /// Gives you a [`MyPooledConn`](struct.MyPooledConn.html).
    ///
    /// `MyPool` will check that connection is alive via
    /// [`MyConn#ping`](../struct.MyConn.html#method.ping) and will
    /// call [`MyConn#reset`](../struct.MyConn.html#method.reset) if
    /// necessary.
    pub fn get_conn(&self) -> MyResult<MyPooledConn> {
        let mut pool = self.pool.lock();

        while pool.pool.is_empty() {
            if pool.count < pool.max {
                match pool.new_conn() {
                    Ok(()) => {
                        pool.count += 1;
                        break;
                    },
                    Err(err) => return Err(err)
                }
            } else {
                pool.cond.wait();
            }
        }

        let mut conn = pool.pool.pop().unwrap();

        if !conn.ping() {
            try!(conn.reset());
        }

        Ok(MyPooledConn {pool: self.clone(), conn: Some(conn)})
    }

    /// You can call `query` and `prepare` directly on a pool but be aware of
    /// the fact that you can't guarantee that query will be called on concrete
    /// connection.
    ///
    /// For example:
    ///
    /// ```ignore
    /// let opts = MyOpts{user: Some("root".to_string()), ..Default::default()};
    /// let pool = MyPool::new(opts).unwrap();
    ///
    /// pool.query("USE some_database");
    /// let result = pool.query("INSERT INTO users (name) VALUES ('Steven')");
    /// let result = pool.query("SELECT * FROM users"); // Error! `no database selected`
    ///                                                 // because PooledConn on which
    ///                                                 // you have executed USE was
    ///                                                 // borrowed by result shadowed
    ///                                                 // on previous line and will not
    ///                                                 // be available until the end of
    ///                                                 // its scope.
    /// ```
    pub fn query<'a>(&'a self, query: &'a str) -> MyResult<QueryResult<'a>> {
        let conn = try!(self.get_conn());
        conn.pooled_query(query)
    }

    /// See docs on [`Pool#query`](#method.query)
    pub fn prepare<'a>(&'a self, query: &'a str) -> MyResult<Stmt<'a>> {
        let conn = try!(self.get_conn());
        conn.pooled_prepare(query)
    }
}

/// Pooled mysql connection which will return to the pool at the end of its
/// scope.
pub struct MyPooledConn {
    pool: MyPool,
    conn: Option<MyConn>
}

impl Drop for MyPooledConn {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        if pool.count > pool.min || self.conn.is_none() {
            pool.count -= 1;
        } else {
            pool.pool.push(self.conn.take().unwrap());
        }
        pool.cond.signal();
    }
}

impl MyPooledConn {
    /// Redirects to
    /// [`MyConn#query`](../struct.MyConn.html#method.query).
    pub fn query<'a>(&'a mut self, query: &str) -> MyResult<QueryResult<'a>> {
        self.conn.as_mut().unwrap().query(query)
    }

    /// Redirects to
    /// [`MyConn#prepare`](../struct.MyConn.html#method.prepare).
    pub fn prepare<'a>(&'a mut self, query: &str) -> MyResult<Stmt<'a>> {
        self.conn.as_mut().unwrap().prepare(query)
    }

    /// Gives mutable reference to the wrapped
    /// [`MyConn`](../struct.MyConn.html).
    pub fn as_mut<'a>(&'a mut self) -> &'a mut MyConn {
        self.conn.as_mut().unwrap()
    }

    /// Gives reference to the wrapped
    /// [`MyConn`](../struct.MyConn.html).
    pub fn as_ref<'a>(&'a self) -> &'a MyConn {
        self.conn.as_ref().unwrap()
    }

    /// Unwraps wrapped [`MyConn`](../struct.MyConn.html).
    pub fn unwrap(mut self) -> MyConn {
        self.conn.take().unwrap()
    }

    fn pooled_query(mut self, query: &str) -> MyResult<QueryResult> {
        match self.as_mut()._query(query) {
            Ok((columns, ok_packet)) => Ok(QueryResult::new_pooled(self,
                                                                   columns,
                                                                   ok_packet,
                                                                   false)),
            Err(err) => Err(err)
        }
    }

    fn pooled_prepare(mut self, query: &str) -> MyResult<Stmt> {
        match self.as_mut()._prepare(query) {
            Ok(stmt) => Ok(Stmt::new_pooled(stmt, self)),
            Err(err) => Err(err)
        }
    }
}

#[cfg(test)]
mod test {
    use conn::{MyOpts};
    use std::default::{Default};
    use super::{MyPool};
    use super::super::super::value::{Bytes, Int};

    static USER: &'static str = "root";
    static PASS: &'static str = "password";
    static ADDR: &'static str = "127.0.0.1";
    static PORT: u16          = 3307;

    #[cfg(feature = "openssl")]
    fn get_opts() -> MyOpts {
        MyOpts {
            user: Some(USER.to_string()),
            pass: Some(PASS.to_string()),
            tcp_addr: Some(ADDR.to_string()),
            tcp_port: PORT,
            ssl_opts: Some((Path::new("tests/ca-cert.pem"), None)),
            ..Default::default()
        }
    }

    #[cfg(not(feature = "ssl"))]
    fn get_opts() -> MyOpts {
        MyOpts {
            user: Some(USER.to_string()),
            pass: Some(PASS.to_string()),
            tcp_addr: Some(ADDR.to_string()),
            tcp_port: PORT,
            ..Default::default()
        }
    }

    #[test]
    fn test_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                assert!(conn.query("SELECT 1").is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let result = pool.query("SELECT 1");
                assert!(result.is_ok());
                let mut result = result.unwrap();
                assert_eq!(result.next(), Some(Ok(vec![Bytes(vec![0x31u8])])));
            });
        }
    }

    #[test]
    fn test_prepared_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                let stmt = conn.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                assert!(stmt.execute([]).is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_prepared_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let stmt = pool.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                for _ in range(0u, 5u) {
                    let result = stmt.execute([]);
                    assert!(result.is_ok());
                    let mut result = result.unwrap();
                    assert_eq!(result.next(), Some(Ok(vec![Int(1)])));
                    assert_eq!(result.next(), None);
                }
            });
        }
    }
}
<commit_msg>Ignore pool doctest<commit_after>use sync::{Arc, Mutex};
use super::super::error::{MyDriverError, InvalidPoolConstraints};
use super::{MyConn, MyOpts, Stmt, QueryResult};
use super::super::error::{MyResult};

struct MyInnerPool {
    opts: MyOpts,
    pool: Vec<MyConn>,
    min: uint,
    max: uint,
    count: uint
}

impl MyInnerPool {
    fn new(min: uint, max: uint, opts: MyOpts) -> MyResult<MyInnerPool> {
        if min > max || max == 0 {
            return Err(MyDriverError(InvalidPoolConstraints));
        }
        let mut pool = MyInnerPool {
            opts: opts,
            pool: Vec::with_capacity(max),
            max: max,
            min: min,
            count: 0
        };
        for _ in range(0, min) {
            try!(pool.new_conn());
        }
        Ok(pool)
    }
    fn new_conn(&mut self) -> MyResult<()> {
        match MyConn::new(self.opts.clone()) {
            Ok(conn) => {
                self.pool.push(conn);
                Ok(())
            },
            Err(err) => Err(err)
        }
    }
}

/// Pool which is holding mysql connections.
///
/// It will hold at least `min` connections and will create as many as `max`
/// connections.
///
/// ```ignore
/// use mysql::conn::{MyOpts};
/// use std::default::{Default};
/// use mysql::conn::pool::{MyPool};
/// use mysql::value::{ToValue};
///
/// fn main() {
///     # let opts = MyOpts{user: Some("root".to_string()),
///     #                   pass: Some("password".to_string()),
///     #                   tcp_addr: Some("127.0.0.1".to_string()),
///     #                   tcp_port: 3307,
///     #                   ..Default::default()};
///     let pool = MyPool::new(opts);
///     assert!(pool.is_ok());
///     let pool = pool.unwrap();
///     for _ in range(0u, 100) {
///         let pool = pool.clone();
///         spawn(proc() {
///             let conn = pool.get_conn();
///             assert!(conn.is_ok());
///             let mut conn = conn.unwrap();
///             let result = conn.query("SELECT 1");
///             assert!(result.is_ok());
///             let mut result = result.unwrap();
///             assert_eq!(result.next(), Some(Ok(vec!["1".to_value()])));
///         });
///     }
/// }
/// ```
#[deriving(Clone)]
pub struct MyPool {
    pool: Arc<Mutex<MyInnerPool>>
}

impl MyPool {
    /// Creates new pool with `min = 10` and `max = 100`.
    pub fn new(opts: MyOpts) -> MyResult<MyPool> {
        MyPool::new_manual(10, 100, opts)
    }

    /// Same as `new` but you can set `min` and `max`.
    pub fn new_manual(min: uint, max: uint, opts: MyOpts) -> MyResult<MyPool> {
        let pool = try!(MyInnerPool::new(min, max, opts));
        Ok(MyPool{ pool: Arc::new(Mutex::new(pool)) })
    }

    /// Gives you a [`MyPooledConn`](struct.MyPooledConn.html).
    ///
    /// `MyPool` will check that connection is alive via
    /// [`MyConn#ping`](../struct.MyConn.html#method.ping) and will
    /// call [`MyConn#reset`](../struct.MyConn.html#method.reset) if
    /// necessary.
    pub fn get_conn(&self) -> MyResult<MyPooledConn> {
        let mut pool = self.pool.lock();

        while pool.pool.is_empty() {
            if pool.count < pool.max {
                match pool.new_conn() {
                    Ok(()) => {
                        pool.count += 1;
                        break;
                    },
                    Err(err) => return Err(err)
                }
            } else {
                pool.cond.wait();
            }
        }

        let mut conn = pool.pool.pop().unwrap();

        if !conn.ping() {
            try!(conn.reset());
        }

        Ok(MyPooledConn {pool: self.clone(), conn: Some(conn)})
    }

    /// You can call `query` and `prepare` directly on a pool but be aware of
    /// the fact that you can't guarantee that query will be called on concrete
    /// connection.
    ///
    /// For example:
    ///
    /// ```ignore
    /// let opts = MyOpts{user: Some("root".to_string()), ..Default::default()};
    /// let pool = MyPool::new(opts).unwrap();
    ///
    /// pool.query("USE some_database");
    /// let result = pool.query("INSERT INTO users (name) VALUES ('Steven')");
    /// let result = pool.query("SELECT * FROM users"); // Error! `no database selected`
    ///                                                 // because PooledConn on which
    ///                                                 // you have executed USE was
    ///                                                 // borrowed by result shadowed
    ///                                                 // on previous line and will not
    ///                                                 // be available until the end of
    ///                                                 // its scope.
    /// ```
    pub fn query<'a>(&'a self, query: &'a str) -> MyResult<QueryResult<'a>> {
        let conn = try!(self.get_conn());
        conn.pooled_query(query)
    }

    /// See docs on [`Pool#query`](#method.query)
    pub fn prepare<'a>(&'a self, query: &'a str) -> MyResult<Stmt<'a>> {
        let conn = try!(self.get_conn());
        conn.pooled_prepare(query)
    }
}

/// Pooled mysql connection which will return to the pool at the end of its
/// scope.
pub struct MyPooledConn {
    pool: MyPool,
    conn: Option<MyConn>
}

impl Drop for MyPooledConn {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        if pool.count > pool.min || self.conn.is_none() {
            pool.count -= 1;
        } else {
            pool.pool.push(self.conn.take().unwrap());
        }
        pool.cond.signal();
    }
}

impl MyPooledConn {
    /// Redirects to
    /// [`MyConn#query`](../struct.MyConn.html#method.query).
    pub fn query<'a>(&'a mut self, query: &str) -> MyResult<QueryResult<'a>> {
        self.conn.as_mut().unwrap().query(query)
    }

    /// Redirects to
    /// [`MyConn#prepare`](../struct.MyConn.html#method.prepare).
    pub fn prepare<'a>(&'a mut self, query: &str) -> MyResult<Stmt<'a>> {
        self.conn.as_mut().unwrap().prepare(query)
    }

    /// Gives mutable reference to the wrapped
    /// [`MyConn`](../struct.MyConn.html).
    pub fn as_mut<'a>(&'a mut self) -> &'a mut MyConn {
        self.conn.as_mut().unwrap()
    }

    /// Gives reference to the wrapped
    /// [`MyConn`](../struct.MyConn.html).
    pub fn as_ref<'a>(&'a self) -> &'a MyConn {
        self.conn.as_ref().unwrap()
    }

    /// Unwraps wrapped [`MyConn`](../struct.MyConn.html).
    pub fn unwrap(mut self) -> MyConn {
        self.conn.take().unwrap()
    }

    fn pooled_query(mut self, query: &str) -> MyResult<QueryResult> {
        match self.as_mut()._query(query) {
            Ok((columns, ok_packet)) => Ok(QueryResult::new_pooled(self,
                                                                   columns,
                                                                   ok_packet,
                                                                   false)),
            Err(err) => Err(err)
        }
    }

    fn pooled_prepare(mut self, query: &str) -> MyResult<Stmt> {
        match self.as_mut()._prepare(query) {
            Ok(stmt) => Ok(Stmt::new_pooled(stmt, self)),
            Err(err) => Err(err)
        }
    }
}

#[cfg(test)]
mod test {
    use conn::{MyOpts};
    use std::default::{Default};
    use super::{MyPool};
    use super::super::super::value::{Bytes, Int};

    static USER: &'static str = "root";
    static PASS: &'static str = "password";
    static ADDR: &'static str = "127.0.0.1";
    static PORT: u16          = 3307;

    #[cfg(feature = "openssl")]
    fn get_opts() -> MyOpts {
        MyOpts {
            user: Some(USER.to_string()),
            pass: Some(PASS.to_string()),
            tcp_addr: Some(ADDR.to_string()),
            tcp_port: PORT,
            ssl_opts: Some((Path::new("tests/ca-cert.pem"), None)),
            ..Default::default()
        }
    }

    #[cfg(not(feature = "ssl"))]
    fn get_opts() -> MyOpts {
        MyOpts {
            user: Some(USER.to_string()),
            pass: Some(PASS.to_string()),
            tcp_addr: Some(ADDR.to_string()),
            tcp_port: PORT,
            ..Default::default()
        }
    }

    #[test]
    fn test_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                assert!(conn.query("SELECT 1").is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let result = pool.query("SELECT 1");
                assert!(result.is_ok());
                let mut result = result.unwrap();
                assert_eq!(result.next(), Some(Ok(vec![Bytes(vec![0x31u8])])));
            });
        }
    }

    #[test]
    fn test_prepared_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                let stmt = conn.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                assert!(stmt.execute([]).is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_prepared_query() {
        let pool = MyPool::new(get_opts());
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0u, 10u) {
            let pool = pool.clone();
            spawn(proc() {
                let stmt = pool.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                for _ in range(0u, 5u) {
                    let result = stmt.execute([]);
                    assert!(result.is_ok());
                    let mut result = result.unwrap();
                    assert_eq!(result.next(), Some(Ok(vec![Int(1)])));
                    assert_eq!(result.next(), None);
                }
            });
        }
    }
}
<|endoftext|>