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

#![allow(unused)]

fn f() {
    let x = 0;
    macro_rules! foo { () => {
        assert_eq!(x, 0);
    } }

    let x = 1;
    foo!();
}

fn g() {
    let x = 0;
    macro_rules! m { ($x:ident) => {
        macro_rules! m2 { () => { ($x, x) } }
        let x = 1;
        macro_rules! m3 { () => { ($x, x) } }
    } }

    let x = 2;
    m!(x);

    let x = 3;
    assert_eq!(m2!(), (2, 0));
    assert_eq!(m3!(), (2, 1));

    let x = 4;
    m!(x);
    assert_eq!(m2!(), (4, 0));
    assert_eq!(m3!(), (4, 1));
}

mod foo {
    macro_rules! m {
        ($f:ident : |$x:ident| $e:expr) => {
            pub fn $f() -> (i32, i32) {
                let x = 0;
                let $x = 1;
                (x, $e)
            }
        }
    }

    m!(f: |x| x + 10);
}

fn interpolated_pattern() {
    let x = 0;
    macro_rules! m {
        ($p:pat, $e:expr) => {
            let $p = 1;
            assert_eq!((x, $e), (0, 1));
        }
    }

    m!(x, x);
}

fn patterns_in_macro_generated_macros() {
    let x = 0;
    macro_rules! m {
        ($a:expr, $b:expr) => {
            assert_eq!(x, 0);
            let x = $a;
            macro_rules! n {
                () => {
                    (x, $b)
                }
            }
        }
    }

    let x = 1;
    m!(2, x);

    let x = 3;
    assert_eq!(n!(), (2, 1));
}

fn match_hygiene() {
    let x = 0;

    macro_rules! m {
        ($p:pat, $e:expr) => {
            for result in &[Ok(1), Err(1)] {
                match *result {
                    $p => { assert_eq!(($e, x), (1, 0)); }
                    Err(x) => { assert_eq!(($e, x), (2, 1)); }
                }
            }
        }
    }

    let x = 2;
    m!(Ok(x), x);
}

fn main() {
    f();
    g();
    assert_eq!(foo::f(), (0, 11));
    interpolated_pattern();
    patterns_in_macro_generated_macros();
    match_hygiene();
}
<commit_msg>Add labels hygiene test<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(unused)]

fn f() {
    let x = 0;
    macro_rules! foo { () => {
        assert_eq!(x, 0);
    } }

    let x = 1;
    foo!();
}

fn g() {
    let x = 0;
    macro_rules! m { ($x:ident) => {
        macro_rules! m2 { () => { ($x, x) } }
        let x = 1;
        macro_rules! m3 { () => { ($x, x) } }
    } }

    let x = 2;
    m!(x);

    let x = 3;
    assert_eq!(m2!(), (2, 0));
    assert_eq!(m3!(), (2, 1));

    let x = 4;
    m!(x);
    assert_eq!(m2!(), (4, 0));
    assert_eq!(m3!(), (4, 1));
}

mod foo {
    macro_rules! m {
        ($f:ident : |$x:ident| $e:expr) => {
            pub fn $f() -> (i32, i32) {
                let x = 0;
                let $x = 1;
                (x, $e)
            }
        }
    }

    m!(f: |x| x + 10);
}

fn interpolated_pattern() {
    let x = 0;
    macro_rules! m {
        ($p:pat, $e:expr) => {
            let $p = 1;
            assert_eq!((x, $e), (0, 1));
        }
    }

    m!(x, x);
}

fn patterns_in_macro_generated_macros() {
    let x = 0;
    macro_rules! m {
        ($a:expr, $b:expr) => {
            assert_eq!(x, 0);
            let x = $a;
            macro_rules! n {
                () => {
                    (x, $b)
                }
            }
        }
    }

    let x = 1;
    m!(2, x);

    let x = 3;
    assert_eq!(n!(), (2, 1));
}

fn match_hygiene() {
    let x = 0;

    macro_rules! m {
        ($p:pat, $e:expr) => {
            for result in &[Ok(1), Err(1)] {
                match *result {
                    $p => { assert_eq!(($e, x), (1, 0)); }
                    Err(x) => { assert_eq!(($e, x), (2, 1)); }
                }
            }
        }
    }

    let x = 2;
    m!(Ok(x), x);
}

fn label_hygiene() {
    'a: loop {
        macro_rules! m { () => { break 'a; } }
        m!();
    }
}

fn main() {
    f();
    g();
    assert_eq!(foo::f(), (0, 11));
    interpolated_pattern();
    patterns_in_macro_generated_macros();
    match_hygiene();
}
<|endoftext|>


<commit_before>
use std;
import std::int;
import std::str::eq;

fn test_to_str() {
    assert (eq(int::to_str(0, 10u), "0"));
    assert (eq(int::to_str(1, 10u), "1"));
    assert (eq(int::to_str(-1, 10u), "-1"));
    assert (eq(int::to_str(255, 16u), "ff"));
    assert (eq(int::to_str(100, 10u), "100"));
}

fn test_pow() {
    assert (int::pow(0, 0u) == 1);
    assert (int::pow(0, 1u) == 0);
    assert (int::pow(0, 2u) == 0);
    assert (int::pow(-1, 0u) == -1);
    assert (int::pow(1, 0u) == 1);
    assert (int::pow(-3, 2u) == 9);
    assert (int::pow(-3, 3u) == -27);
    assert (int::pow(4, 9u) == 262144);
}

fn main() { test_to_str(); }<commit_msg>Begin running the test for int::pow<commit_after>
use std;
import std::int;
import std::str::eq;

fn test_to_str() {
    assert (eq(int::to_str(0, 10u), "0"));
    assert (eq(int::to_str(1, 10u), "1"));
    assert (eq(int::to_str(-1, 10u), "-1"));
    assert (eq(int::to_str(255, 16u), "ff"));
    assert (eq(int::to_str(100, 10u), "100"));
}

fn test_pow() {
    assert (int::pow(0, 0u) == 1);
    assert (int::pow(0, 1u) == 0);
    assert (int::pow(0, 2u) == 0);
    assert (int::pow(-1, 0u) == 1);
    assert (int::pow(1, 0u) == 1);
    assert (int::pow(-3, 2u) == 9);
    assert (int::pow(-3, 3u) == -27);
    assert (int::pow(4, 9u) == 262144);
}

fn main() {
  test_to_str();
  test_pow();
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use chrono::{DateTime, Local};
use log::debug;
use serde::{Deserialize, Serialize};
use serde_yaml;

use crate::error::{Error, Result};
use crate::utils::markdown_to_html;

/// blog post headers
///
/// the blog post headers is parsed using yaml format.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostHeaders {
    /// post created local time, `created: 1970-01-01T00:00:00+08:00`
    pub created: DateTime<Local>,
    /// post hidden flag, `hidden: true`, default `false`
    #[serde(default)]
    pub hidden: bool,
    /// post tags, `tags: [hello, world]`, default `[]`
    #[serde(default)]
    pub tags: Vec<String>,
    /// post description
    #[serde(default)]
    pub description: String,
}

/// blog post
///
/// every blog post is composed of `head` part and `body` part.
/// the two part is separated by the first blank line.
#[derive(Serialize)]
pub struct Post {
    /// blog root path
    root: PathBuf,
    /// post path from relative root directory
    pub path: PathBuf,
    /// the post title
    pub title: String,
    /// the post url
    pub url: PathBuf,
    /// post headers
    pub headers: PostHeaders,
    /// post html body
    pub content: String,
}

impl Post {
    pub fn new<P: AsRef<Path>>(root: P, path: P) -> Result<Post> {
        let root = root.as_ref();
        let path = path.as_ref();
        debug!("loading post: {}", path.display());

        let fp = root.join(&path);
        let mut fo = File::open(fp)?;
        let mut content = String::new();
        fo.read_to_string(&mut content)?;

        let v: Vec<&str> = content.splitn(2, "\n\n").collect();
        if v.len() != 2 {
            return Err(Error::PostOnlyOnePart(path.into()));
        }
        let head = v[0].trim();
        let body = v[1].trim();
        if head.is_empty() {
            return Err(Error::PostNoHead(path.into()));
        }
        if head.is_empty() {
            return Err(Error::PostNoBody(path.into()));
        }

        let title = path
            .file_stem()
            .and_then(|x| x.to_str())
            .expect(&format!("post filename format error: {}", path.display()));
        let url = Path::new("/").join(path).with_extension("html");
        let mut headers: PostHeaders = serde_yaml::from_str(head)?;
        if headers.description.is_empty() {
            let desc = body
                .split("\n\n")
                .take(1)
                .next()
                .unwrap_or("")
                .split_whitespace()
                .take(100)
                .collect::<Vec<_>>()
                .join(" ");
            headers.description.push_str(&desc);
            if !headers.description.is_empty() {
                headers.description.push_str("...");
            }
        }
        let content = markdown_to_html(body);

        Ok(Post {
            root: root.to_owned(),
            path: path.to_owned(),
            title: title.to_owned(),
            url,
            headers,
            content,
        })
    }

    /// the absolute path of blog post markdown file.
    pub fn src(&self) -> PathBuf {
        self.root.join(&self.path)
    }

    /// the absolute path of blog post html file.
    pub fn dest(&self) -> PathBuf {
        self.path.with_extension("html")
    }
}
<commit_msg>fix now it check if body is empty<commit_after>use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use chrono::{DateTime, Local};
use log::debug;
use serde::{Deserialize, Serialize};
use serde_yaml;

use crate::error::{Error, Result};
use crate::utils::markdown_to_html;

/// blog post headers
///
/// the blog post headers is parsed using yaml format.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostHeaders {
    /// post created local time, `created: 1970-01-01T00:00:00+08:00`
    pub created: DateTime<Local>,
    /// post hidden flag, `hidden: true`, default `false`
    #[serde(default)]
    pub hidden: bool,
    /// post tags, `tags: [hello, world]`, default `[]`
    #[serde(default)]
    pub tags: Vec<String>,
    /// post description
    #[serde(default)]
    pub description: String,
}

/// blog post
///
/// every blog post is composed of `head` part and `body` part.
/// the two part is separated by the first blank line.
#[derive(Serialize)]
pub struct Post {
    /// blog root path
    root: PathBuf,
    /// post path from relative root directory
    pub path: PathBuf,
    /// the post title
    pub title: String,
    /// the post url
    pub url: PathBuf,
    /// post headers
    pub headers: PostHeaders,
    /// post html body
    pub content: String,
}

impl Post {
    pub fn new<P: AsRef<Path>>(root: P, path: P) -> Result<Post> {
        let root = root.as_ref();
        let path = path.as_ref();
        debug!("loading post: {}", path.display());

        let fp = root.join(&path);
        let mut fo = File::open(fp)?;
        let mut content = String::new();
        fo.read_to_string(&mut content)?;

        let v: Vec<&str> = content.splitn(2, "\n\n").collect();
        if v.len() != 2 {
            return Err(Error::PostOnlyOnePart(path.into()));
        }
        let head = v[0].trim();
        let body = v[1].trim();
        if head.is_empty() {
            return Err(Error::PostNoHead(path.into()));
        }
        if body.is_empty() {
            return Err(Error::PostNoBody(path.into()));
        }

        let title = path
            .file_stem()
            .and_then(|x| x.to_str())
            .expect(&format!("post filename format error: {}", path.display()));
        let url = Path::new("/").join(path).with_extension("html");
        let mut headers: PostHeaders = serde_yaml::from_str(head)?;
        if headers.description.is_empty() {
            let desc = body
                .split("\n\n")
                .take(1)
                .next()
                .unwrap_or("")
                .split_whitespace()
                .take(100)
                .collect::<Vec<_>>()
                .join(" ");
            headers.description.push_str(&desc);
            if !headers.description.is_empty() {
                headers.description.push_str("...");
            }
        }
        let content = markdown_to_html(body);

        Ok(Post {
            root: root.to_owned(),
            path: path.to_owned(),
            title: title.to_owned(),
            url,
            headers,
            content,
        })
    }

    /// the absolute path of blog post markdown file.
    pub fn src(&self) -> PathBuf {
        self.root.join(&self.path)
    }

    /// the absolute path of blog post html file.
    pub fn dest(&self) -> PathBuf {
        self.path.with_extension("html")
    }
}
<|endoftext|>


<commit_before>/**
 * > Every morning in the early part of October 1843, on my coming down to
 *   breakfast, your brother William Edward and yourself used to ask me: "Well,
 *   Papa, can you multiply triples?" Whereto I was always obliged to reply,
 *   with a sad shake of the head, "No, I can only add and subtract them."
 *
 *   Sir William Hamilton
 */

use core::cast::transmute;
use core::cmp::{Eq, Ord};
use core::ptr::to_unsafe_ptr;
use core::sys::size_of;
use core::vec::raw::buf_as_slice;

use std::cmp::FuzzyEq;

use angle::Angle;
use dim::{Dimensional, ToPtr};
use funs::common::*;
use funs::exponential::*;
use funs::triganomic::*;
use mat::{Mat3, Mat4};
use num::kinds::{Float, Number};
use vec::Vec3;

/**
 * The base quaternion trait
 *
 * # Type parameters
 *
 * * `T` - The type of the components. Should be a floating point type.
 * * `V3` - The 3-dimensional vector type that will containin the imaginary
 *          components of the quaternion.
 */
pub trait Quaternion<T,V3>: Dimensional<T>, ToPtr<T>, Eq, Neg<self> {
    static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> self;

    /**
     * # Return value
     *
     * The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
     */
    static pure fn identity() -> self;

    /**
     * # Return value
     *
     * The additive identity, ie: `q = 0 + 0i + 0j + 0i`
     */
    static pure fn zero() -> self;

    /**
     * # Return value
     *
     * The result of multiplying the quaternion a scalar
     */
    pure fn mul_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The result of dividing the quaternion a scalar
     */
    pure fn div_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The result of multiplying the quaternion by a vector
     */
    pure fn mul_v(&self, vec: &V3) -> V3;

    /**
     * # Return value
     *
     * The sum of this quaternion and `other`
     */
    pure fn add_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The sum of this quaternion and `other`
     */
    pure fn sub_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The the result of multipliplying the quaternion by `other`
     */
    pure fn mul_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The dot product of the quaternion and `other`
     */
    pure fn dot(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The conjugate of the quaternion
     */
    pure fn conjugate(&self) -> self;

    /**
     * # Return value
     *
     * The multiplicative inverse of the quaternion
     */
    pure fn inverse(&self) -> self;

    /**
     * # Return value
     *
     * The squared magnitude of the quaternion. This is useful for
     * magnitude comparisons where the exact magnitude does not need to be
     * calculated.
     */
    pure fn magnitude2(&self) -> T;

    /**
     * # Return value
     *
     * The magnitude of the quaternion
     *
     * # Performance notes
     *
     * For instances where the exact magnitude of the quaternion does not need
     * to be known, for example for quaternion-quaternion magnitude comparisons,
     * it is advisable to use the `magnitude2` method instead.
     */
    pure fn magnitude(&self) -> T;

    /**
     * # Return value
     *
     * The normalized quaternion
     */
    pure fn normalize(&self) -> self;

    /**
     * Normalised linear interpolation
     *
     * # Return value
     *
     * The intoperlated quaternion
     */
    pure fn nlerp(&self, other: &self, amount: T) -> self;

    /**
     * Perform a spherical linear interpolation between the quaternion and
     * `other`.
     *
     * # Return value
     *
     * The intoperlated quaternion
     *
     * # Performance notes
     *
     * This is more accurate than `nlerp` but is also more
     * computationally intensive.
     */
    pure fn slerp(&self, other: &self, amount: T) -> self;

    /**
     * Convert the quaternion to a 3 x 3 rotation matrix
     */
    pure fn to_mat3(&self) -> Mat3<T>;

    /**
     * Convert the quaternion to a 4 x 4 transformation matrix
     */
    pure fn to_mat4(&self) -> Mat4<T>;
}

pub trait ToQuat<T> {
    /**
     * Convert `self` to a quaternion
     */
    pure fn to_Quat() -> Quat<T>;
}

/**
 * A quaternion in scalar/vector form
 *
 * # Type parameters
 *
 * * `T` - The type of the components. Should be a floating point type.
 *
 * # Fields
 *
 * * `s` - the scalar component
 * * `v` - a vector containing the three imaginary components
 */
pub struct Quat<T> { s: T, v: Vec3<T> }

pub impl<T> Quat<T> {
    /**
     * Construct the quaternion from one scalar component and three
     * imaginary components
     *
     * # Arguments
     *
     * * `w`  - the scalar component
     * * `xi` - the fist imaginary component
     * * `yj` - the second imaginary component
     * * `zk` - the third imaginary component
     */
    #[inline(always)]
    static pure fn new(w: T, xi: T, yj: T, zk: T) -> Quat<T> {
        Quat::from_sv(move w, move Vec3::new(move xi, move yj, move zk))
    }

    /**
     * Construct the quaternion from a scalar and a vector
     *
     * # Arguments
     *
     * * `s` - the scalar component
     * * `v` - a vector containing the three imaginary components
     */
    #[inline(always)]
    static pure fn from_sv(s: T, v: Vec3<T>) -> Quat<T> {
        Quat { s: move s, v: move v }
    }
}

pub impl<T> Quat<T>: Dimensional<T> {
    #[inline(always)]
    static pure fn dim() -> uint { 4 }

    #[inline(always)]
    static pure fn size_of() -> uint { size_of::<Quat<T>>() }
}

pub impl<T:Copy> Quat<T>: Index<uint, T> {
    #[inline(always)]
    pure fn index(i: uint) -> T {
        unsafe { do buf_as_slice(self.to_ptr(), 4) |slice| { slice[i] } }
    }
}

pub impl<T:Copy> Quat<T>: ToPtr<T> {
    #[inline(always)]
    pure fn to_ptr(&self) -> *T {
        unsafe {
            transmute::<*Quat<T>, *T>(
                to_unsafe_ptr(&*self)
            )
        }
    }
}

pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T, Vec3<T>> {
    #[inline(always)]
    static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> Quat<T> {
        let half = theta.to_radians() / Number::from(2);
        Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
    }

    #[inline(always)]
    static pure fn identity() -> Quat<T> {
        Quat::new(Number::from(1),
                  Number::from(0),
                  Number::from(0),
                  Number::from(0))
    }

    #[inline(always)]
    static pure fn zero() -> Quat<T> {
        Quat::new(Number::from(0),
                  Number::from(0),
                  Number::from(0),
                  Number::from(0))
    }

    #[inline(always)]
    pure fn mul_t(&self, value: T) -> Quat<T> {
        Quat::new(self[0] * value,
                  self[1] * value,
                  self[2] * value,
                  self[3] * value)
    }

    #[inline(always)]
    pure fn div_t(&self, value: T) -> Quat<T> {
        Quat::new(self[0] / value,
                  self[1] / value,
                  self[2] / value,
                  self[3] / value)
    }

    #[inline(always)]
    pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T>  {
        let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s));
        self.v.cross(&tmp).mul_t(Number::from(2)).add_v(vec)
    }

    #[inline(always)]
    pure fn add_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] + other[0],
                  self[1] + other[1],
                  self[2] + other[2],
                  self[3] + other[3])
    }

    #[inline(always)]
    pure fn sub_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] - other[0],
                  self[1] - other[1],
                  self[2] - other[2],
                  self[3] - other[3])
    }

    #[inline(always)]
    pure fn mul_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self.s * other.s   - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z,
                  self.s * other.v.x + self.v.x * other.s   + self.v.y * other.v.z - self.v.z * other.v.y,
                  self.s * other.v.y + self.v.y * other.s   + self.v.z * other.v.x - self.v.x * other.v.z,
                  self.s * other.v.z + self.v.z * other.s   + self.v.x * other.v.y - self.v.y * other.v.x)
    }

    #[inline(always)]
    pure fn dot(&self, other: &Quat<T>) -> T {
        self.s * other.s + self.v.dot(&other.v)
    }

    #[inline(always)]
    pure fn conjugate(&self) -> Quat<T> {
        Quat::from_sv(self.s, -self.v)
    }

    #[inline(always)]
    pure fn inverse(&self) -> Quat<T> {
        self.conjugate().div_t(self.magnitude2())
    }

    #[inline(always)]
    pure fn magnitude2(&self) -> T {
        self.s * self.s + self.v.length2()
    }

    #[inline(always)]
    pure fn magnitude(&self) -> T {
        self.magnitude2().sqrt()
    }

    #[inline(always)]
    pure fn normalize(&self) -> Quat<T> {
        let mut n: T = Number::from(1);
        n /= self.magnitude();
        return self.mul_t(n);
    }

    #[inline(always)]
    pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
        let _1: T = Number::from(1);
        self.mul_t(_1 - amount).add_q(&other.mul_t(amount)).normalize()
    }

    /**
     * Spherical Linear Intoperlation
     *
     * Both quaternions should be normalized first, or else strange things will
     * will happen...
     *
     * # Performance notes
     *
     * The `acos` operation used in `slerp` is an expensive operation, so unless
     * your quarternions a far away from each other it's generally more advisable
     * to use `nlerp` when you know your rotations are going to be small.
     *
     * - [Understanding Slerp, Then Not Using It]
     *   (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
     * - [Arcsynthesis OpenGL tutorial]
     *   (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
     */
    #[inline(always)]
    pure fn slerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
        let dot = self.dot(other);

        // if quaternions are close together use `nlerp`
        let dot_threshold = Number::from(0.9995);
        if dot > dot_threshold { return self.nlerp(other, amount) }

        let robust_dot = dot.clamp(&-Number::from(1), &Number::from(1));    // stay within the domain of acos()
        let theta_0 = acos(&robust_dot);                    // the angle between the quaternions
        let theta = theta_0 * amount;                       // the fraction of theta specified by `amount`

        let q = other.sub_q(&self.mul_t(robust_dot))
                     .normalize();

        self.mul_t(cos(&theta)).add_q(&q.mul_t(sin(&theta)))
    }

    #[inline(always)]
    pure fn to_mat3(&self) -> Mat3<T> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        let _1: T = Number::from(1);

        Mat3::new(_1 - yy2 - zz2,      xy2 + sz2,      xz2 - sy2,
                       xy2 - sz2, _1 - xx2 - zz2,      yz2 + sx2,
                       xz2 + sy2,      yz2 - sx2, _1 - xx2 - yy2)
    }

    #[inline(always)]
    pure fn to_mat4(&self) -> Mat4<T> {
        self.to_mat3().to_mat4()
    }
}

pub impl<T:Copy Num> Quat<T>: Neg<Quat<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Quat<T> {
        Quat::new(-self[0], -self[1], -self[2], -self[3])
    }
}

pub impl<T:Copy Eq> Quat<T>: Eq {
    #[inline(always)]
    pure fn eq(&self, other: &Quat<T>) -> bool {
        self[0] == other[0] &&
        self[1] == other[1] &&
        self[2] == other[2] &&
        self[3] == other[3]
    }

    #[inline(always)]
    pure fn ne(&self, other: &Quat<T>) -> bool {
        !(self == other)
    }
}

pub impl<T:Copy FuzzyEq> Quat<T>: FuzzyEq {
    #[inline(always)]
    pure fn fuzzy_eq(other: &Quat<T>) -> bool {
        self[0].fuzzy_eq(&other[0]) &&
        self[1].fuzzy_eq(&other[1]) &&
        self[2].fuzzy_eq(&other[2]) &&
        self[3].fuzzy_eq(&other[3])
    }
}<commit_msg>Make slerp method implementation a little easier to understand<commit_after>/**
 * > Every morning in the early part of October 1843, on my coming down to
 *   breakfast, your brother William Edward and yourself used to ask me: "Well,
 *   Papa, can you multiply triples?" Whereto I was always obliged to reply,
 *   with a sad shake of the head, "No, I can only add and subtract them."
 *
 *   Sir William Hamilton
 */

use core::cast::transmute;
use core::cmp::{Eq, Ord};
use core::ptr::to_unsafe_ptr;
use core::sys::size_of;
use core::vec::raw::buf_as_slice;

use std::cmp::FuzzyEq;

use angle::Angle;
use dim::{Dimensional, ToPtr};
use funs::common::*;
use funs::exponential::*;
use funs::triganomic::*;
use mat::{Mat3, Mat4};
use num::kinds::{Float, Number};
use vec::Vec3;

/**
 * The base quaternion trait
 *
 * # Type parameters
 *
 * * `T` - The type of the components. Should be a floating point type.
 * * `V3` - The 3-dimensional vector type that will containin the imaginary
 *          components of the quaternion.
 */
pub trait Quaternion<T,V3>: Dimensional<T>, ToPtr<T>, Eq, Neg<self> {
    static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> self;

    /**
     * # Return value
     *
     * The multiplicative identity, ie: `q = 1 + 0i + 0j + 0i`
     */
    static pure fn identity() -> self;

    /**
     * # Return value
     *
     * The additive identity, ie: `q = 0 + 0i + 0j + 0i`
     */
    static pure fn zero() -> self;

    /**
     * # Return value
     *
     * The result of multiplying the quaternion a scalar
     */
    pure fn mul_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The result of dividing the quaternion a scalar
     */
    pure fn div_t(&self, value: T) -> self;

    /**
     * # Return value
     *
     * The result of multiplying the quaternion by a vector
     */
    pure fn mul_v(&self, vec: &V3) -> V3;

    /**
     * # Return value
     *
     * The sum of this quaternion and `other`
     */
    pure fn add_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The sum of this quaternion and `other`
     */
    pure fn sub_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The the result of multipliplying the quaternion by `other`
     */
    pure fn mul_q(&self, other: &self) -> self;

    /**
     * # Return value
     *
     * The dot product of the quaternion and `other`
     */
    pure fn dot(&self, other: &self) -> T;

    /**
     * # Return value
     *
     * The conjugate of the quaternion
     */
    pure fn conjugate(&self) -> self;

    /**
     * # Return value
     *
     * The multiplicative inverse of the quaternion
     */
    pure fn inverse(&self) -> self;

    /**
     * # Return value
     *
     * The squared magnitude of the quaternion. This is useful for
     * magnitude comparisons where the exact magnitude does not need to be
     * calculated.
     */
    pure fn magnitude2(&self) -> T;

    /**
     * # Return value
     *
     * The magnitude of the quaternion
     *
     * # Performance notes
     *
     * For instances where the exact magnitude of the quaternion does not need
     * to be known, for example for quaternion-quaternion magnitude comparisons,
     * it is advisable to use the `magnitude2` method instead.
     */
    pure fn magnitude(&self) -> T;

    /**
     * # Return value
     *
     * The normalized quaternion
     */
    pure fn normalize(&self) -> self;

    /**
     * Normalised linear interpolation
     *
     * # Return value
     *
     * The intoperlated quaternion
     */
    pure fn nlerp(&self, other: &self, amount: T) -> self;

    /**
     * Perform a spherical linear interpolation between the quaternion and
     * `other`.
     *
     * # Return value
     *
     * The intoperlated quaternion
     *
     * # Performance notes
     *
     * This is more accurate than `nlerp` but is also more
     * computationally intensive.
     */
    pure fn slerp(&self, other: &self, amount: T) -> self;

    /**
     * Convert the quaternion to a 3 x 3 rotation matrix
     */
    pure fn to_mat3(&self) -> Mat3<T>;

    /**
     * Convert the quaternion to a 4 x 4 transformation matrix
     */
    pure fn to_mat4(&self) -> Mat4<T>;
}

pub trait ToQuat<T> {
    /**
     * Convert `self` to a quaternion
     */
    pure fn to_Quat() -> Quat<T>;
}

/**
 * A quaternion in scalar/vector form
 *
 * # Type parameters
 *
 * * `T` - The type of the components. Should be a floating point type.
 *
 * # Fields
 *
 * * `s` - the scalar component
 * * `v` - a vector containing the three imaginary components
 */
pub struct Quat<T> { s: T, v: Vec3<T> }

pub impl<T> Quat<T> {
    /**
     * Construct the quaternion from one scalar component and three
     * imaginary components
     *
     * # Arguments
     *
     * * `w`  - the scalar component
     * * `xi` - the fist imaginary component
     * * `yj` - the second imaginary component
     * * `zk` - the third imaginary component
     */
    #[inline(always)]
    static pure fn new(w: T, xi: T, yj: T, zk: T) -> Quat<T> {
        Quat::from_sv(move w, move Vec3::new(move xi, move yj, move zk))
    }

    /**
     * Construct the quaternion from a scalar and a vector
     *
     * # Arguments
     *
     * * `s` - the scalar component
     * * `v` - a vector containing the three imaginary components
     */
    #[inline(always)]
    static pure fn from_sv(s: T, v: Vec3<T>) -> Quat<T> {
        Quat { s: move s, v: move v }
    }
}

pub impl<T> Quat<T>: Dimensional<T> {
    #[inline(always)]
    static pure fn dim() -> uint { 4 }

    #[inline(always)]
    static pure fn size_of() -> uint { size_of::<Quat<T>>() }
}

pub impl<T:Copy> Quat<T>: Index<uint, T> {
    #[inline(always)]
    pure fn index(i: uint) -> T {
        unsafe { do buf_as_slice(self.to_ptr(), 4) |slice| { slice[i] } }
    }
}

pub impl<T:Copy> Quat<T>: ToPtr<T> {
    #[inline(always)]
    pure fn to_ptr(&self) -> *T {
        unsafe {
            transmute::<*Quat<T>, *T>(
                to_unsafe_ptr(&*self)
            )
        }
    }
}

pub impl<T:Copy Float Exp Extent InvTrig> Quat<T>: Quaternion<T, Vec3<T>> {
    #[inline(always)]
    static pure fn from_axis_angle<A:Angle<T>>(axis: &Vec3<T>, theta: A) -> Quat<T> {
        let half = theta.to_radians() / Number::from(2);
        Quat::from_sv(cos(&half), axis.mul_t(sin(&half)))
    }

    #[inline(always)]
    static pure fn identity() -> Quat<T> {
        Quat::new(Number::from(1),
                  Number::from(0),
                  Number::from(0),
                  Number::from(0))
    }

    #[inline(always)]
    static pure fn zero() -> Quat<T> {
        Quat::new(Number::from(0),
                  Number::from(0),
                  Number::from(0),
                  Number::from(0))
    }

    #[inline(always)]
    pure fn mul_t(&self, value: T) -> Quat<T> {
        Quat::new(self[0] * value,
                  self[1] * value,
                  self[2] * value,
                  self[3] * value)
    }

    #[inline(always)]
    pure fn div_t(&self, value: T) -> Quat<T> {
        Quat::new(self[0] / value,
                  self[1] / value,
                  self[2] / value,
                  self[3] / value)
    }

    #[inline(always)]
    pure fn mul_v(&self, vec: &Vec3<T>) -> Vec3<T>  {
        let tmp = self.v.cross(vec).add_v(&vec.mul_t(self.s));
        self.v.cross(&tmp).mul_t(Number::from(2)).add_v(vec)
    }

    #[inline(always)]
    pure fn add_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] + other[0],
                  self[1] + other[1],
                  self[2] + other[2],
                  self[3] + other[3])
    }

    #[inline(always)]
    pure fn sub_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self[0] - other[0],
                  self[1] - other[1],
                  self[2] - other[2],
                  self[3] - other[3])
    }

    #[inline(always)]
    pure fn mul_q(&self, other: &Quat<T>) -> Quat<T> {
        Quat::new(self.s * other.s   - self.v.x * other.v.x - self.v.y * other.v.y - self.v.z * other.v.z,
                  self.s * other.v.x + self.v.x * other.s   + self.v.y * other.v.z - self.v.z * other.v.y,
                  self.s * other.v.y + self.v.y * other.s   + self.v.z * other.v.x - self.v.x * other.v.z,
                  self.s * other.v.z + self.v.z * other.s   + self.v.x * other.v.y - self.v.y * other.v.x)
    }

    #[inline(always)]
    pure fn dot(&self, other: &Quat<T>) -> T {
        self.s * other.s + self.v.dot(&other.v)
    }

    #[inline(always)]
    pure fn conjugate(&self) -> Quat<T> {
        Quat::from_sv(self.s, -self.v)
    }

    #[inline(always)]
    pure fn inverse(&self) -> Quat<T> {
        self.conjugate().div_t(self.magnitude2())
    }

    #[inline(always)]
    pure fn magnitude2(&self) -> T {
        self.s * self.s + self.v.length2()
    }

    #[inline(always)]
    pure fn magnitude(&self) -> T {
        self.magnitude2().sqrt()
    }

    #[inline(always)]
    pure fn normalize(&self) -> Quat<T> {
        let mut n: T = Number::from(1);
        n /= self.magnitude();
        return self.mul_t(n);
    }

    #[inline(always)]
    pure fn nlerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
        let _1: T = Number::from(1);
        self.mul_t(_1 - amount).add_q(&other.mul_t(amount)).normalize()
    }

    /**
     * Spherical Linear Intoperlation
     *
     * Both quaternions should be normalized first, or else strange things will
     * will happen...
     *
     * # Performance notes
     *
     * The `acos` operation used in `slerp` is an expensive operation, so unless
     * your quarternions a far away from each other it's generally more advisable
     * to use `nlerp` when you know your rotations are going to be small.
     *
     * - [Understanding Slerp, Then Not Using It]
     *   (http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/)
     * - [Arcsynthesis OpenGL tutorial]
     *   (http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Interpolation.html)
     */
    #[inline(always)]
    pure fn slerp(&self, other: &Quat<T>, amount: T) -> Quat<T> {
        let dot = self.dot(other);

        let dot_threshold = Number::from(0.9995);

        if dot > dot_threshold {
            return self.nlerp(other, amount);                   // if quaternions are close together use `nlerp`
        } else {
            let robust_dot = dot.clamp(&-Number::from(1),
                                       &Number::from(1));       // stay within the domain of acos()

            let theta_0 = acos(&robust_dot);                    // the angle between the quaternions
            let theta = theta_0 * amount;                       // the fraction of theta specified by `amount`

            let q = other.sub_q(&self.mul_t(robust_dot))
                         .normalize();

            return self.mul_t(cos(&theta)).add_q(&q.mul_t(sin(&theta)));
        }
    }

    #[inline(always)]
    pure fn to_mat3(&self) -> Mat3<T> {
        let x2 = self.v.x + self.v.x;
        let y2 = self.v.y + self.v.y;
        let z2 = self.v.z + self.v.z;

        let xx2 = x2 * self.v.x;
        let xy2 = x2 * self.v.y;
        let xz2 = x2 * self.v.z;

        let yy2 = y2 * self.v.y;
        let yz2 = y2 * self.v.z;
        let zz2 = z2 * self.v.z;

        let sy2 = y2 * self.s;
        let sz2 = z2 * self.s;
        let sx2 = x2 * self.s;

        let _1: T = Number::from(1);

        Mat3::new(_1 - yy2 - zz2,      xy2 + sz2,      xz2 - sy2,
                       xy2 - sz2, _1 - xx2 - zz2,      yz2 + sx2,
                       xz2 + sy2,      yz2 - sx2, _1 - xx2 - yy2)
    }

    #[inline(always)]
    pure fn to_mat4(&self) -> Mat4<T> {
        self.to_mat3().to_mat4()
    }
}

pub impl<T:Copy Num> Quat<T>: Neg<Quat<T>> {
    #[inline(always)]
    pure fn neg(&self) -> Quat<T> {
        Quat::new(-self[0], -self[1], -self[2], -self[3])
    }
}

pub impl<T:Copy Eq> Quat<T>: Eq {
    #[inline(always)]
    pure fn eq(&self, other: &Quat<T>) -> bool {
        self[0] == other[0] &&
        self[1] == other[1] &&
        self[2] == other[2] &&
        self[3] == other[3]
    }

    #[inline(always)]
    pure fn ne(&self, other: &Quat<T>) -> bool {
        !(self == other)
    }
}

pub impl<T:Copy FuzzyEq> Quat<T>: FuzzyEq {
    #[inline(always)]
    pure fn fuzzy_eq(other: &Quat<T>) -> bool {
        self[0].fuzzy_eq(&other[0]) &&
        self[1].fuzzy_eq(&other[1]) &&
        self[2].fuzzy_eq(&other[2]) &&
        self[3].fuzzy_eq(&other[3])
    }
}<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate rustbox;

use std::collections::dlist::DList;
use std::comm::{Receiver, Sender};
use std::io::{File, BufferedReader};
use std::str::from_utf8;

pub struct Editor {
    pub sender: Sender<rustbox::Event>,
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buffer>,
    pub cursor_x: int,
    pub cursor_y: int,
}

pub struct Buffer {
    pub lines: DList<Line>,
    pub active: bool,
    pub num_lines: int,
}

#[deriving(Clone)]
pub struct Line {
    pub data: String,
}

pub enum Response {
    Continue,
    Quit,
}

impl Buffer {
    pub fn new() -> Buffer {
        Buffer {
            lines: DList::new(),
            active: false,
            num_lines: 0,
        }
    }

    pub fn new_from_file(filename: String) -> Buffer {
        let path = Path::new(filename.to_string());

        let mut new_buffer = Buffer::new();
        let mut file = BufferedReader::new(File::open(&path));
        let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

        for line in lines.iter() {
            new_buffer.lines.push(Line{data: line.clone()})
        }

        new_buffer
    }
}

impl Line {
    pub fn new() -> Line {
        Line {
            data: String::new(),
        }
    }
}

impl Editor {
    pub fn new(filenames: &[String]) -> Editor {
        let mut buffers = Vec::new();

        for filename in filenames.iter() {
            let mut b = Buffer::new_from_file(filename.clone());
            b.active = true;
            buffers.push(b);
        }

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            buffers: buffers,
            cursor_x: 0,
            cursor_y: 0,
        }
    }

    pub fn handle_key_event(&mut self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            Some('h') => { self.cursor_x -= 1; Continue },
            Some('j') => { self.cursor_y += 1; Continue },
            Some('k') => { self.cursor_y -= 1; Continue },
            Some('l') => { self.cursor_x += 1; Continue },
            _ => Continue,
        }
    }

    pub fn draw(&mut self) {
        for buffer in self.buffers.iter() {
            if buffer.active {
                for (index, line) in buffer.lines.iter().enumerate() {
                    rustbox::print(0, index, rustbox::Bold, rustbox::White, rustbox::Black, line.data.clone());
                }
            }
        }
        rustbox::set_cursor(self.cursor_x, self.cursor_y);
    }

    pub fn start(&mut self) -> bool {
        loop {
            self.draw();
            rustbox::present();
            match self.events.try_recv() {
                Ok(rustbox::KeyEvent(_, _, ch)) => {
                    match self.handle_key_event(ch) {
                        Quit => break,
                        _ => {}
                    }
                },
                TryRecvError => {}
            }
        }
        return false
    }

}

<commit_msg>Add some comments<commit_after>#![feature(macro_rules)]

extern crate rustbox;

use std::collections::dlist::DList;
use std::comm::{Receiver, Sender};
use std::io::{File, BufferedReader};
use std::str::from_utf8;

pub struct Editor {
    pub sender: Sender<rustbox::Event>,
    pub events: Receiver<rustbox::Event>,
    pub buffers: Vec<Buffer>,
    pub cursor_x: int,
    pub cursor_y: int,
}

pub struct Buffer {
    pub lines: DList<Line>,
    pub active: bool,
    pub num_lines: int,
}

#[deriving(Clone)]
pub struct Line {
    pub data: String,
}

pub enum Response {
    Continue,
    Quit,
}

impl Buffer {
    pub fn new() -> Buffer {
        Buffer {
            lines: DList::new(),
            active: false,
            num_lines: 0,
        }
    }

    pub fn new_from_file(filename: String) -> Buffer {
        let path = Path::new(filename.to_string());

        let mut new_buffer = Buffer::new();
        let mut file = BufferedReader::new(File::open(&path));
        let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();

        for line in lines.iter() {
            new_buffer.lines.push(Line{data: line.clone()})
        }

        new_buffer
    }
}

impl Line {
    pub fn new() -> Line {
        Line {
            data: String::new(),
        }
    }
}

impl Editor {
    pub fn new(filenames: &[String]) -> Editor {
        let mut buffers = Vec::new();

        for filename in filenames.iter() {
            let mut b = Buffer::new_from_file(filename.clone());
            b.active = true;
            buffers.push(b);
        }

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            buffers: buffers,
            cursor_x: 0,
            cursor_y: 0,
        }
    }

    pub fn handle_key_event(&mut self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,

            // cursor movement
            Some('h') => { self.cursor_x -= 1; Continue },
            Some('j') => { self.cursor_y += 1; Continue },
            Some('k') => { self.cursor_y -= 1; Continue },
            Some('l') => { self.cursor_x += 1; Continue },

            // default
            _ => Continue,
        }
    }

    pub fn draw(&mut self) {
        // TODO: change this to only draw the active buffer
        for buffer in self.buffers.iter() {
            if buffer.active {
                for (index, line) in buffer.lines.iter().enumerate() {
                    rustbox::print(0, index, rustbox::Bold, rustbox::White, rustbox::Black, line.data.clone());
                }
            }
        }
        rustbox::set_cursor(self.cursor_x, self.cursor_y);
    }

    pub fn start(&mut self) -> bool {
        loop {
            self.draw();
            rustbox::present();
            match self.events.try_recv() {
                Ok(rustbox::KeyEvent(_, _, ch)) => {
                    match self.handle_key_event(ch) {
                        Quit => break,
                        _ => {}
                    }
                },
                TryRecvError => {}
            }
        }
        return false
    }

}

<|endoftext|>


<commit_before>use std::mem;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use consts::{Af,Arphrd,AddrFamily,IfaF,Iff,Ntf,Nud,RtaType,RtmF,Rtn,Rtprot,RtScope,RtTable};
use err::{SerError,DeError};

/// Struct representing interface information messages
pub struct Ifinfomsg {
    /// Interface address family
    pub ifi_family: AddrFamily,
    /// Interface type
    pub ifi_type: Arphrd,
    /// Interface index
    pub ifi_index: libc::c_int,
    /// Interface flags
    pub ifi_flags: Vec<Iff>,
    ifi_change: libc::c_uint,
}

impl Ifinfomsg {
    /// Create a fully initialized interface info struct
    pub fn new(ifi_family: AddrFamily, ifi_type: Arphrd, ifi_index: libc::c_int, ifi_flags: Vec<Iff>) -> Self {
        Ifinfomsg { ifi_family, ifi_type, ifi_index, ifi_flags, ifi_change: 0xffffffff }
    }
}

impl Nl for Ifinfomsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifi_family.serialize(buf)?;
        self.ifi_type.serialize(buf)?;
        self.ifi_index.serialize(buf)?;
        self.ifi_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ifi_change.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifinfomsg {
            ifi_family: AddrFamily::deserialize(buf)?,
            ifi_type: Arphrd::deserialize(buf)?,
            ifi_index: libc::c_int::deserialize(buf)?,
            ifi_flags: {
                let flags = libc::c_uint::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_int>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push(bit.into());
                    }
                }
                nl_flags
            },
            ifi_change: 0xffffffff,
        })
    }

    fn size(&self) -> usize {
        self.ifi_family.size() + self.ifi_type.size() + self.ifi_index.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Struct representing interface address messages
pub struct Ifaddrmsg {
    /// Interface address family
    pub ifa_family: Af,
    /// Interface address prefix length
    pub ifa_prefixlen: libc::c_uchar,
    /// Interface address flags
    pub ifa_flags: Vec<IfaF>,
    /// Interface address scope
    pub ifa_scope: libc::c_uchar,
    /// Interface address index
    pub ifa_index: libc::c_int,
}

impl Nl for Ifaddrmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifa_family.serialize(buf)?;
        self.ifa_prefixlen.serialize(buf)?;
        self.ifa_flags.iter().fold(0, |acc: libc::c_uchar, next| {
            let next_uint: u32 = next.into();
            acc | next_uint as libc::c_uchar
        }).serialize(buf)?;
        self.ifa_scope.serialize(buf)?;
        self.ifa_index.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifaddrmsg {
            ifa_family: Af::deserialize(buf)?,
            ifa_prefixlen: libc::c_uchar::deserialize(buf)?,
            ifa_flags: {
                let flags = libc::c_uchar::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uchar>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push((bit as u32).into());
                    }
                }
                nl_flags
            },
            ifa_scope: libc::c_uchar::deserialize(buf)?,
            ifa_index: libc::c_int::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ifa_family.size() + self.ifa_prefixlen.size() + mem::size_of::<libc::c_uchar>()
            + self.ifa_scope.size() + self.ifa_index.size()
    }
}

/// Route message
pub struct Rtmsg {
    /// Address family of route
    pub rtm_family: libc::c_uchar,
    /// Length of destination
    pub rtm_dst_len: libc::c_uchar,
    /// Length of source
    pub rtm_src_len: libc::c_uchar,
    /// TOS filter
    pub rtm_tos: libc::c_uchar,
    /// Routing table ID
    pub rtm_table: RtTable,
    /// Routing protocol
    pub rtm_protocol: Rtprot,
    /// Routing scope
    pub rtm_scope: RtScope,
    /// Routing type
    pub rtm_type: Rtn,
    /// Routing flags
    pub rtm_flags: Vec<RtmF>,
}

impl Nl for Rtmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rtm_family.serialize(buf)?;
        self.rtm_dst_len.serialize(buf)?;
        self.rtm_src_len.serialize(buf)?;
        self.rtm_tos.serialize(buf)?;
        self.rtm_table.serialize(buf)?;
        self.rtm_protocol.serialize(buf)?;
        self.rtm_scope.serialize(buf)?;
        self.rtm_type.serialize(buf)?;
        self.rtm_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Rtmsg {
            rtm_family: libc::c_uchar::deserialize(buf)?,
            rtm_dst_len: libc::c_uchar::deserialize(buf)?,
            rtm_src_len: libc::c_uchar::deserialize(buf)?,
            rtm_tos: libc::c_uchar::deserialize(buf)?,
            rtm_table: RtTable::deserialize(buf)?,
            rtm_protocol: Rtprot::deserialize(buf)?,
            rtm_scope: RtScope::deserialize(buf)?,
            rtm_type: Rtn::deserialize(buf)?,
            rtm_flags: {
                let flags = libc::c_int::deserialize(buf)?;
                let mut rtm_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uint>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        rtm_flags.push((bit as libc::c_uint).into());
                    }
                }
                rtm_flags
            },
        })
    }

    fn size(&self) -> usize {
        self.rtm_family.size() + self.rtm_dst_len.size() + self.rtm_src_len.size()
            + self.rtm_tos.size() + self.rtm_table.size() + self.rtm_protocol.size()
            + self.rtm_scope.size() + self.rtm_type.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Represents an ARP (neighbor table) entry
pub struct Ndmsg {
    /// Address family of entry
    pub ndm_family: Af,
    /// Index of entry
    pub ndm_index: libc::c_int,
    /// State of entry
    pub ndm_state: Vec<Nud>,
    /// Flags for entry
    pub ndm_flags: Vec<Ntf>,
    /// Type of entry
    pub ndm_type: Rtn,
}

impl Nl for Ndmsg {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ndm_family.serialize(buf)?;
        self.ndm_index.serialize(buf)?;
        self.ndm_state.iter().fold(0, |acc: u16, next| {
            let next_uint: u16 = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ndm_flags.iter().fold(0, |acc: u8, next| {
            let next_uint: u8 = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ndm_type.serialize(buf)?;
        Ok(())
    }

    fn size(&self) -> usize {
        self.ndm_family.size() + self.ndm_index.size() + mem::size_of::<u16>() +
            mem::size_of::<u8>() + self.ndm_type.size()
    }
}

/// Struct representing ARP cache info
pub struct NdaCacheinfo {
    /// Confirmed
    pub ndm_confirmed: u32,
    /// Used
    pub ndm_used: u32,
    /// Updated
    pub ndm_updated: u32,
    /// Reference count
    pub ndm_refcnt: u32,
}

impl Nl for NdaCacheinfo {
    type SerIn = ();
    type DeIn = ();

    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ndm_confirmed.serialize(buf)?;
        self.ndm_used.serialize(buf)?;
        self.ndm_updated.serialize(buf)?;
        self.ndm_refcnt.serialize(buf)?;
        Ok(())
    }

    fn size(&self) -> usize {
        self.ndm_confirmed.size() + self.ndm_used.size() + self.ndm_updated.size() +
            self.ndm_refcnt.size()
    }
}

/// Struct representing route netlink attributes
pub struct RtAttr<T, P> {
    /// Length of the attribute
    pub rta_len: libc::c_ushort,
    /// Type of the attribute
    pub rta_type: T,
    /// Payload of the attribute
    pub rta_payload: P,
}

impl<T, P> Nl for RtAttr<T, P> where T: RtaType, P: Nl {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rta_len.serialize(buf)?;
        self.rta_type.serialize(buf)?;
        self.rta_payload.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(RtAttr {
            rta_len: libc::c_ushort::deserialize(buf)?,
            rta_type: T::deserialize(buf)?,
            rta_payload: P::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.rta_len.size() + self.rta_type.size() + self.rta_payload.size()
    }
}
<commit_msg>Add missing deserialize impls for structs and remove SerIn/DeIn<commit_after>use std::mem;

use buffering::copy::{StreamReadBuffer,StreamWriteBuffer};
use libc;

use Nl;
use consts::{Af,Arphrd,AddrFamily,IfaF,Iff,Ntf,Nud,RtaType,RtmF,Rtn,Rtprot,RtScope,RtTable};
use err::{SerError,DeError};

/// Struct representing interface information messages
pub struct Ifinfomsg {
    /// Interface address family
    pub ifi_family: AddrFamily,
    /// Interface type
    pub ifi_type: Arphrd,
    /// Interface index
    pub ifi_index: libc::c_int,
    /// Interface flags
    pub ifi_flags: Vec<Iff>,
    ifi_change: libc::c_uint,
}

impl Ifinfomsg {
    /// Create a fully initialized interface info struct
    pub fn new(ifi_family: AddrFamily, ifi_type: Arphrd, ifi_index: libc::c_int, ifi_flags: Vec<Iff>) -> Self {
        Ifinfomsg { ifi_family, ifi_type, ifi_index, ifi_flags, ifi_change: 0xffffffff }
    }
}

impl Nl for Ifinfomsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifi_family.serialize(buf)?;
        self.ifi_type.serialize(buf)?;
        self.ifi_index.serialize(buf)?;
        self.ifi_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ifi_change.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifinfomsg {
            ifi_family: AddrFamily::deserialize(buf)?,
            ifi_type: Arphrd::deserialize(buf)?,
            ifi_index: libc::c_int::deserialize(buf)?,
            ifi_flags: {
                let flags = libc::c_uint::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_int>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push(bit.into());
                    }
                }
                nl_flags
            },
            ifi_change: 0xffffffff,
        })
    }

    fn size(&self) -> usize {
        self.ifi_family.size() + self.ifi_type.size() + self.ifi_index.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Struct representing interface address messages
pub struct Ifaddrmsg {
    /// Interface address family
    pub ifa_family: Af,
    /// Interface address prefix length
    pub ifa_prefixlen: libc::c_uchar,
    /// Interface address flags
    pub ifa_flags: Vec<IfaF>,
    /// Interface address scope
    pub ifa_scope: libc::c_uchar,
    /// Interface address index
    pub ifa_index: libc::c_int,
}

impl Nl for Ifaddrmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ifa_family.serialize(buf)?;
        self.ifa_prefixlen.serialize(buf)?;
        self.ifa_flags.iter().fold(0, |acc: libc::c_uchar, next| {
            let next_uint: u32 = next.into();
            acc | next_uint as libc::c_uchar
        }).serialize(buf)?;
        self.ifa_scope.serialize(buf)?;
        self.ifa_index.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Ifaddrmsg {
            ifa_family: Af::deserialize(buf)?,
            ifa_prefixlen: libc::c_uchar::deserialize(buf)?,
            ifa_flags: {
                let flags = libc::c_uchar::deserialize(buf)?;
                let mut nl_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uchar>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        nl_flags.push((bit as u32).into());
                    }
                }
                nl_flags
            },
            ifa_scope: libc::c_uchar::deserialize(buf)?,
            ifa_index: libc::c_int::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ifa_family.size() + self.ifa_prefixlen.size() + mem::size_of::<libc::c_uchar>()
            + self.ifa_scope.size() + self.ifa_index.size()
    }
}

/// Route message
pub struct Rtmsg {
    /// Address family of route
    pub rtm_family: libc::c_uchar,
    /// Length of destination
    pub rtm_dst_len: libc::c_uchar,
    /// Length of source
    pub rtm_src_len: libc::c_uchar,
    /// TOS filter
    pub rtm_tos: libc::c_uchar,
    /// Routing table ID
    pub rtm_table: RtTable,
    /// Routing protocol
    pub rtm_protocol: Rtprot,
    /// Routing scope
    pub rtm_scope: RtScope,
    /// Routing type
    pub rtm_type: Rtn,
    /// Routing flags
    pub rtm_flags: Vec<RtmF>,
}

impl Nl for Rtmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rtm_family.serialize(buf)?;
        self.rtm_dst_len.serialize(buf)?;
        self.rtm_src_len.serialize(buf)?;
        self.rtm_tos.serialize(buf)?;
        self.rtm_table.serialize(buf)?;
        self.rtm_protocol.serialize(buf)?;
        self.rtm_scope.serialize(buf)?;
        self.rtm_type.serialize(buf)?;
        self.rtm_flags.iter().fold(0, |acc: libc::c_uint, next| {
            let next_uint: libc::c_uint = next.into();
            acc | next_uint
        }).serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(Rtmsg {
            rtm_family: libc::c_uchar::deserialize(buf)?,
            rtm_dst_len: libc::c_uchar::deserialize(buf)?,
            rtm_src_len: libc::c_uchar::deserialize(buf)?,
            rtm_tos: libc::c_uchar::deserialize(buf)?,
            rtm_table: RtTable::deserialize(buf)?,
            rtm_protocol: Rtprot::deserialize(buf)?,
            rtm_scope: RtScope::deserialize(buf)?,
            rtm_type: Rtn::deserialize(buf)?,
            rtm_flags: {
                let flags = libc::c_int::deserialize(buf)?;
                let mut rtm_flags = Vec::new();
                for i in 0..mem::size_of::<libc::c_uint>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        rtm_flags.push((bit as libc::c_uint).into());
                    }
                }
                rtm_flags
            },
        })
    }

    fn size(&self) -> usize {
        self.rtm_family.size() + self.rtm_dst_len.size() + self.rtm_src_len.size()
            + self.rtm_tos.size() + self.rtm_table.size() + self.rtm_protocol.size()
            + self.rtm_scope.size() + self.rtm_type.size() + mem::size_of::<libc::c_uint>()
    }
}

/// Represents an ARP (neighbor table) entry
pub struct Ndmsg {
    /// Address family of entry
    pub ndm_family: Af,
    /// Index of entry
    pub ndm_index: libc::c_int,
    /// State of entry
    pub ndm_state: Vec<Nud>,
    /// Flags for entry
    pub ndm_flags: Vec<Ntf>,
    /// Type of entry
    pub ndm_type: Rtn,
}

impl Nl for Ndmsg {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ndm_family.serialize(buf)?;
        self.ndm_index.serialize(buf)?;
        self.ndm_state.iter().fold(0, |acc: u16, next| {
            let next_uint: u16 = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ndm_flags.iter().fold(0, |acc: u8, next| {
            let next_uint: u8 = next.into();
            acc | next_uint
        }).serialize(buf)?;
        self.ndm_type.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
            where B: AsRef<[u8]> {
        Ok(Ndmsg {
            ndm_family: Af::deserialize(buf)?,
            ndm_index: libc::c_int::deserialize(buf)?,
            ndm_state: {
                let state = u16::deserialize(buf)?;
                let mut ndm_state = Vec::new();
                for i in 0..mem::size_of::<u16>() * 8 {
                    let bit = 1 << i;
                    if bit & state == bit {
                        ndm_state.push((bit as u16).into());
                    }
                }
                ndm_state
            },
            ndm_flags: {
                let flags = u8::deserialize(buf)?;
                let mut ndm_flags = Vec::new();
                for i in 0..mem::size_of::<u16>() * 8 {
                    let bit = 1 << i;
                    if bit & flags == bit {
                        ndm_flags.push((bit as u8).into());
                    }
                }
                ndm_flags
            },
            ndm_type: Rtn::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ndm_family.size() + self.ndm_index.size() + mem::size_of::<u16>() +
            mem::size_of::<u8>() + self.ndm_type.size()
    }
}

/// Struct representing ARP cache info
pub struct NdaCacheinfo {
    /// Confirmed
    pub ndm_confirmed: u32,
    /// Used
    pub ndm_used: u32,
    /// Updated
    pub ndm_updated: u32,
    /// Reference count
    pub ndm_refcnt: u32,
}

impl Nl for NdaCacheinfo {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.ndm_confirmed.serialize(buf)?;
        self.ndm_used.serialize(buf)?;
        self.ndm_updated.serialize(buf)?;
        self.ndm_refcnt.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
            where B: AsRef<[u8]> {
        Ok(NdaCacheinfo {
            ndm_confirmed: u32::deserialize(buf)?,
            ndm_used: u32::deserialize(buf)?,
            ndm_updated: u32::deserialize(buf)?,
            ndm_refcnt: u32::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.ndm_confirmed.size() + self.ndm_used.size() + self.ndm_updated.size() +
            self.ndm_refcnt.size()
    }
}

/// Struct representing route netlink attributes
pub struct RtAttr<T, P> {
    /// Length of the attribute
    pub rta_len: libc::c_ushort,
    /// Type of the attribute
    pub rta_type: T,
    /// Payload of the attribute
    pub rta_payload: P,
}

impl<T, P> Nl for RtAttr<T, P> where T: RtaType, P: Nl {
    fn serialize(&self, buf: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.rta_len.serialize(buf)?;
        self.rta_type.serialize(buf)?;
        self.rta_payload.serialize(buf)?;
        Ok(())
    }

    fn deserialize<B>(buf: &mut StreamReadBuffer<B>) -> Result<Self, DeError> where B: AsRef<[u8]> {
        Ok(RtAttr {
            rta_len: libc::c_ushort::deserialize(buf)?,
            rta_type: T::deserialize(buf)?,
            rta_payload: P::deserialize(buf)?,
        })
    }

    fn size(&self) -> usize {
        self.rta_len.size() + self.rta_type.size() + self.rta_payload.size()
    }
}
<|endoftext|>


<commit_before>// Semantics analyzer. This pass plays a few important roles as shown
// below:
//
// - Add types to nodes. For example, a tree that represents "1+2" is
//   typed as INT because the result type of an addition of two
//   integers is integer.
//
// - Insert nodes to make array-to-pointer conversion explicit.
//   Recall that, in C, "array of T" is automatically converted to
//   "pointer to T" in most contexts.
//
// - Scales operands for pointer arithmetic. E.g. ptr+1 becomes ptr+4
//   for integer and becomes ptr+8 for pointer.
//
// - Reject bad assignments, such as `1=2+3`.

use crate::parse::*;
use crate::token::*;
use crate::util::*;
use std::cell::RefCell;
use std::rc::Rc;

fn maybe_decay(base: & mut Node, decay: bool) -> & mut Node {
    if !decay || base.ty.borrow().ty != CType::ARY {
        return base;
    }

    let tmp = base.clone();
    *base = alloc_node();
    base.op = NodeType::ADDR;

    let node_ty = tmp.clone().ty;
    let ty_tmp = *node_ty.borrow().clone().ary_of.unwrap();
    base.ty = Rc::new(RefCell::new(ptr_to(Rc::new(RefCell::new(ty_tmp)))));

    base.expr = Some(Box::new(tmp.clone()));
    base.token = tmp.token.clone();
    return base;
}

macro_rules! bad_node {
    ($node:expr, $msg:expr) => {
        bad_token(&*$node.token.clone().unwrap(), $msg.to_string());
        panic!();
    };
}

fn check_lval(node: Box<Node>) {
    match node.op {
        NodeType::VAR | NodeType::DEREF | NodeType::DOT => { }
        _ => {
            bad_node!(node, "not an lvalue");
        }
    }
}

fn scale_ptr(op: NodeType, base: Node, ty: Type) -> Node {
    let mut node = alloc_node();
    node.op = op;
    node.lhs = Some(Box::new(base.clone()));
    let ptr = ty.ptr_to.unwrap();
    node.rhs = Some(Box::new(new_int_node(ptr.borrow().size, base.token.clone())));
    node.token = base.token.clone();
    return node;
}

fn check_int(node: & Node) {
    if node.ty.borrow().ty != CType::INT {
        if node.ty.borrow().ty != CType::CHAR {
            bad_node!(node, "not an integer");
        }
    }
}

fn walk<'a>(node: &'a mut Node, prog: &'a mut Program) -> &'a Node {
    return do_walk(node, true, prog);
}

fn walk_nodecay<'a>(node: &'a mut Node, prog: &'a mut Program) -> &'a Node {
    return do_walk(node, false, prog);
}

fn do_walk<'a>(node: &'a mut Node, decay: bool, prog: &'a mut Program) -> &'a Node {
    match node.op {
        NodeType::NUM |
            NodeType::NULL |
            NodeType::BREAK |
            NodeType::CONTINUE => {
            return node;
        }
        NodeType::VAR => {
            return maybe_decay(node, decay);
        }
        NodeType::VARDEF => {
            match node.init {
                Some(_) => {
                    node.init = Some(Box::new(walk(&mut *node.init.clone().unwrap(), prog).clone()));
                }
                None => { }
            }
            return node;
        }
        NodeType::IF => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.then = Some(Box::new(walk(&mut *node.then.clone().unwrap(), prog).clone()));

            if node.els.is_some() {
                node.els = Some(Box::new(walk(&mut *node.els.clone().unwrap(), prog).clone()));
            }
            return node;
        }
        NodeType::FOR => {
            node.init = Some(Box::new(walk(&mut *node.init.clone().unwrap(), prog).clone()));
            if let Some(mut cond) = node.cond.clone() {
                node.cond = Some(Box::new(walk(&mut cond, prog).clone()));
            }
            if let Some(mut inc) = node.inc.clone() {
                node.inc = Some(Box::new(walk(&mut inc, prog).clone()));
            }
            node.body = Some(Box::new(walk(&mut *node.body.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::DO_WHILE => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.body = Some(Box::new(walk(&mut *node.body.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::ADD => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.borrow().ty == CType::PTR {
                        //use std::mem;
                        //mem::swap(lhs, rhs);
                        let n = lhs.clone();
                        *lhs = rhs.clone();
                        *rhs = n;
                    }
                }
                _ => {}
            }

            if let Some(ref rhs) = node.rhs {
                check_int(rhs);
            }

            if let Some(ref lhs) = node.lhs {
                if lhs.ty.borrow().ty == CType::PTR {
                    node.rhs = Some(Box::new(scale_ptr(NodeType::MUL, *node.rhs.clone().unwrap(), lhs.ty.borrow().clone())));
                    node.ty = node.lhs.clone().unwrap().ty;
                } else {
                    node.ty = Rc::new(RefCell::new(int_ty()));
                }
            }

            return node;
        }
        NodeType::SUB => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

            let l = &node.rhs.clone().unwrap().ty;
            let r = &node.lhs.clone().unwrap().ty;
            if l.borrow().ty == CType::PTR && r.borrow().ty == CType::PTR {
                if !same_type(r.clone(), l.clone()) {
                    bad_node!(node, "incompatible pointer");
                }
                *node = scale_ptr(NodeType::DIV, node.clone(), l.borrow().clone());
            }

            node.ty = node.lhs.clone().unwrap().ty;
            return node;
        }
        NodeType::ADD_EQ |
            NodeType::SUB_EQ => {
                node.lhs = Some(Box::new(walk_nodecay(&mut *node.lhs.clone().unwrap(), prog).clone()));
                check_lval(node.lhs.clone().unwrap());
                node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
                if let Some(ref lhs) = node.lhs {
                    node.ty = lhs.ty.clone();
                }

                if let Some(ref lhs) = node.lhs {
                    if lhs.ty.borrow().ty == CType::PTR {
                        node.rhs = Some(Box::new(scale_ptr(NodeType::MUL, *node.rhs.clone().unwrap(), lhs.ty.borrow().clone())));
                    }
                }
                return node;
        }

        NodeType::EQL |
            NodeType::MUL_EQ |
            NodeType::DIV_EQ |
            NodeType::MOD_EQ |
            NodeType::SHL_EQ |
            NodeType::SHR_EQ |
            NodeType::AND_EQ |
            NodeType::XOR_EQ |
            NodeType::OR_EQ => {
            node.lhs = Some(Box::new(walk_nodecay(&mut *node.lhs.clone().unwrap(), prog).clone()));
            check_lval(node.lhs.clone().unwrap());

            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
            node.ty = node.lhs.clone().unwrap().ty;
            return node;
        }
        NodeType::DOT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            let node_ty = node.expr.clone().unwrap().ty;
            if node_ty.borrow().ty != CType::STRUCT {
                bad_node!(node, "struct expected before '.'");
            }

            let ty = node.expr.clone().unwrap().ty;
            if ty.borrow().members == None {
                bad_node!(node, format!("incomplete type: {:?}", node.expr));
            }

            for m in ty.borrow().clone().members.unwrap().iter() {
                if m.name != node.name {
                    continue;
                }

                node.ty = m.ty.clone();
                return maybe_decay(node, decay);
            }
            bad_node!(node, format!("member missing: {}", node.name));
        }
        NodeType::QUEST => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.then = Some(Box::new(walk(&mut *node.then.clone().unwrap(), prog).clone()));
            node.els = Some(Box::new(walk(&mut *node.els.clone().unwrap(), prog).clone()));
            node.ty = node.then.clone().unwrap().ty;
            return node;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::MOD |
            NodeType::LT |
            NodeType::OR |
            NodeType::XOR |
            NodeType::AND |
            NodeType::EQ |
            NodeType::NE |
            NodeType::LE |
            NodeType::SHL |
            NodeType::SHR |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
                node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

                check_int(&*node.lhs.clone().unwrap());
                check_int(&*node.rhs.clone().unwrap());

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
                node.ty = Rc::new(RefCell::new(int_ty()));
                return node;
            }
        NodeType::COMMA => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
            node.ty = node.rhs.clone().unwrap().ty;
            return node;
        }
        NodeType::POST_INC | NodeType::POST_DEC => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            node.ty = node.expr.clone().unwrap().ty;
            return node;
        }
        NodeType::EXCLAM | NodeType::NOT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            check_int(&*node.expr.clone().unwrap());
            node.ty = node.expr.clone().unwrap().ty;
            return node;
        }
        NodeType::ADDR => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            check_lval(node.expr.clone().unwrap());
            node.ty = Rc::new(RefCell::new(ptr_to(node.expr.clone().unwrap().ty)));
            return node;
        }
        NodeType::DEREF => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));

            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.borrow().ty != CType::PTR {
                        bad_node!(node, format!("operand must be a pointer: {:?}", expr));
                    }

                    let ptr = expr.ty.borrow().ptr_to.clone().unwrap();
                    if ptr.borrow().ty == CType::VOID {
                        bad_node!(node, "operand dereference void pointer");
                    }
                }
                None => {}
            }

            let ty_tmp = node.expr.clone().unwrap().ty;
            node.ty = ty_tmp.borrow().clone().ptr_to.unwrap();
            return maybe_decay(node, decay);
        }
        NodeType::RETURN |
            NodeType::EXPR_STMT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::CALL => {
            for i in 0..node.args.len() {
                node.args[i] = walk(&mut node.args[i], prog).clone();
            }
            let node_ty = *node.ty.borrow().clone().returning.unwrap();
            node.ty = Rc::new(RefCell::new(node_ty));
            return node;
        }
        NodeType::COMP_STMT => {
            for i in 0..node.stmts.len() {
                node.stmts[i] = walk(&mut node.stmts[i], prog).clone();
            }
            return node;
        }
        NodeType::STMT_EXPR => {
            let mut body = walk(&mut *node.body.clone().unwrap(), prog).clone();

            if body.stmts.len() == 0 {
                bad_node!(node, "empty statement expression");
            }

            let n = body.stmts.pop().unwrap();
            if n.op != NodeType::EXPR_STMT {
                bad_node!(node, "statement expression returning void");
            }

            node.body = Some(Box::new(body));
            node.expr = n.expr.clone();
            node.ty = n.expr.clone().unwrap().ty;
            return node;
        }
        _ => {
            panic!("unknown node type: {:?}", node);
        }
    }
}

pub fn get_type(node: &mut Node) -> Type {
    let mut prog = new_program();
    return walk_nodecay(node, &mut prog).ty.borrow().clone();
}

pub fn sema(prog: &mut Program) {
    let mut funcs = prog.funcs.clone();

    for func in funcs.iter_mut() {
        let node = func.node.clone();
        if node.borrow().op == NodeType::DECL {
            continue;
        }

        assert!(node.borrow().op == NodeType::FUNC);

        let mut args = Vec::new();
        for a in node.borrow_mut().args.iter_mut() {
            args.push(walk(&mut a.clone(), prog).clone());
        }
        node.borrow_mut().args = args;

        let mut body = node.borrow_mut().body.clone().unwrap();
        node.borrow_mut().body = Some(Box::new(walk(&mut body, prog).clone()));

        let mut off = 0;
        for v in func.lvars.iter_mut() {
            off = roundup(off, v.borrow().ty.align);
            off += v.borrow().ty.size;
            v.borrow_mut().offset = off;
        }
        func.stacksize = off;
    }

    prog.funcs = funcs;
}
<commit_msg>Result type of arithmetic experession is promoted to int.<commit_after>// Semantics analyzer. This pass plays a few important roles as shown
// below:
//
// - Add types to nodes. For example, a tree that represents "1+2" is
//   typed as INT because the result type of an addition of two
//   integers is integer.
//
// - Insert nodes to make array-to-pointer conversion explicit.
//   Recall that, in C, "array of T" is automatically converted to
//   "pointer to T" in most contexts.
//
// - Scales operands for pointer arithmetic. E.g. ptr+1 becomes ptr+4
//   for integer and becomes ptr+8 for pointer.
//
// - Reject bad assignments, such as `1=2+3`.

use crate::parse::*;
use crate::token::*;
use crate::util::*;
use std::cell::RefCell;
use std::rc::Rc;

fn maybe_decay(base: & mut Node, decay: bool) -> & mut Node {
    if !decay || base.ty.borrow().ty != CType::ARY {
        return base;
    }

    let tmp = base.clone();
    *base = alloc_node();
    base.op = NodeType::ADDR;

    let node_ty = tmp.clone().ty;
    let ty_tmp = *node_ty.borrow().clone().ary_of.unwrap();
    base.ty = Rc::new(RefCell::new(ptr_to(Rc::new(RefCell::new(ty_tmp)))));

    base.expr = Some(Box::new(tmp.clone()));
    base.token = tmp.token.clone();
    return base;
}

macro_rules! bad_node {
    ($node:expr, $msg:expr) => {
        bad_token(&*$node.token.clone().unwrap(), $msg.to_string());
        panic!();
    };
}

fn check_lval(node: Box<Node>) {
    match node.op {
        NodeType::VAR | NodeType::DEREF | NodeType::DOT => { }
        _ => {
            bad_node!(node, "not an lvalue");
        }
    }
}

fn scale_ptr(op: NodeType, base: Node, ty: Type) -> Node {
    let mut node = alloc_node();
    node.op = op;
    node.lhs = Some(Box::new(base.clone()));
    let ptr = ty.ptr_to.unwrap();
    node.rhs = Some(Box::new(new_int_node(ptr.borrow().size, base.token.clone())));
    node.token = base.token.clone();
    return node;
}

fn check_int(node: & Node) {
    if node.ty.borrow().ty != CType::INT {
        if node.ty.borrow().ty != CType::CHAR {
            bad_node!(node, "not an integer");
        }
    }
}

fn walk<'a>(node: &'a mut Node, prog: &'a mut Program) -> &'a Node {
    return do_walk(node, true, prog);
}

fn walk_nodecay<'a>(node: &'a mut Node, prog: &'a mut Program) -> &'a Node {
    return do_walk(node, false, prog);
}

fn do_walk<'a>(node: &'a mut Node, decay: bool, prog: &'a mut Program) -> &'a Node {
    match node.op {
        NodeType::NUM |
            NodeType::NULL |
            NodeType::BREAK |
            NodeType::CONTINUE => {
            return node;
        }
        NodeType::VAR => {
            return maybe_decay(node, decay);
        }
        NodeType::VARDEF => {
            match node.init {
                Some(_) => {
                    node.init = Some(Box::new(walk(&mut *node.init.clone().unwrap(), prog).clone()));
                }
                None => { }
            }
            return node;
        }
        NodeType::IF => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.then = Some(Box::new(walk(&mut *node.then.clone().unwrap(), prog).clone()));

            if node.els.is_some() {
                node.els = Some(Box::new(walk(&mut *node.els.clone().unwrap(), prog).clone()));
            }
            return node;
        }
        NodeType::FOR => {
            node.init = Some(Box::new(walk(&mut *node.init.clone().unwrap(), prog).clone()));
            if let Some(mut cond) = node.cond.clone() {
                node.cond = Some(Box::new(walk(&mut cond, prog).clone()));
            }
            if let Some(mut inc) = node.inc.clone() {
                node.inc = Some(Box::new(walk(&mut inc, prog).clone()));
            }
            node.body = Some(Box::new(walk(&mut *node.body.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::DO_WHILE => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.body = Some(Box::new(walk(&mut *node.body.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::ADD => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.borrow().ty == CType::PTR {
                        //use std::mem;
                        //mem::swap(lhs, rhs);
                        let n = lhs.clone();
                        *lhs = rhs.clone();
                        *rhs = n;
                    }
                }
                _ => {}
            }

            if let Some(ref rhs) = node.rhs {
                check_int(rhs);
            }

            if let Some(ref lhs) = node.lhs {
                if lhs.ty.borrow().ty == CType::PTR {
                    node.rhs = Some(Box::new(scale_ptr(NodeType::MUL, *node.rhs.clone().unwrap(), lhs.ty.borrow().clone())));
                    node.ty = node.lhs.clone().unwrap().ty;
                } else {
                    node.ty = Rc::new(RefCell::new(int_ty()));
                }
            }

            return node;
        }
        NodeType::SUB => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

            let lty = &node.rhs.clone().unwrap().ty;
            let rty = &node.lhs.clone().unwrap().ty;

            if lty.borrow().ty == CType::PTR && rty.borrow().ty == CType::PTR {
                if !same_type(rty.clone(), lty.clone()) {
                    bad_node!(node, "incompatible pointer");
                }
                *node = scale_ptr(NodeType::DIV, node.clone(), lty.borrow().clone());
                node.ty = lty.clone();
            } else {
                node.ty = Rc::new(RefCell::new(int_ty()));
            }

            node.ty = node.lhs.clone().unwrap().ty;
            return node;
        }
        NodeType::ADD_EQ |
            NodeType::SUB_EQ => {
                node.lhs = Some(Box::new(walk_nodecay(&mut *node.lhs.clone().unwrap(), prog).clone()));
                check_lval(node.lhs.clone().unwrap());
                node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
                if let Some(ref lhs) = node.lhs {
                    node.ty = lhs.ty.clone();
                }

                if let Some(ref lhs) = node.lhs {
                    if lhs.ty.borrow().ty == CType::PTR {
                        node.rhs = Some(Box::new(scale_ptr(NodeType::MUL, *node.rhs.clone().unwrap(), lhs.ty.borrow().clone())));
                        node.ty = lhs.ty.clone();
                    } else {
                        node.ty = Rc::new(RefCell::new(int_ty()));
                    }
                }
                return node;
        }

        NodeType::EQL |
            NodeType::MUL_EQ |
            NodeType::DIV_EQ |
            NodeType::MOD_EQ |
            NodeType::SHL_EQ |
            NodeType::SHR_EQ |
            NodeType::AND_EQ |
            NodeType::XOR_EQ |
            NodeType::OR_EQ => {
            node.lhs = Some(Box::new(walk_nodecay(&mut *node.lhs.clone().unwrap(), prog).clone()));
            check_lval(node.lhs.clone().unwrap());

            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
            node.ty = node.lhs.clone().unwrap().ty;
            return node;
        }
        NodeType::DOT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            let node_ty = node.expr.clone().unwrap().ty;
            if node_ty.borrow().ty != CType::STRUCT {
                bad_node!(node, "struct expected before '.'");
            }

            let ty = node.expr.clone().unwrap().ty;
            if ty.borrow().members == None {
                bad_node!(node, format!("incomplete type: {:?}", node.expr));
            }

            for m in ty.borrow().clone().members.unwrap().iter() {
                if m.name != node.name {
                    continue;
                }

                node.ty = m.ty.clone();
                return maybe_decay(node, decay);
            }
            bad_node!(node, format!("member missing: {}", node.name));
        }
        NodeType::QUEST => {
            node.cond = Some(Box::new(walk(&mut *node.cond.clone().unwrap(), prog).clone()));
            node.then = Some(Box::new(walk(&mut *node.then.clone().unwrap(), prog).clone()));
            node.els = Some(Box::new(walk(&mut *node.els.clone().unwrap(), prog).clone()));
            node.ty = node.then.clone().unwrap().ty;
            return node;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::MOD |
            NodeType::LT |
            NodeType::OR |
            NodeType::XOR |
            NodeType::AND |
            NodeType::EQ |
            NodeType::NE |
            NodeType::LE |
            NodeType::SHL |
            NodeType::SHR |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
                node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));

                check_int(&*node.lhs.clone().unwrap());
                check_int(&*node.rhs.clone().unwrap());

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
                node.ty = Rc::new(RefCell::new(int_ty()));
                return node;
            }
        NodeType::COMMA => {
            node.lhs = Some(Box::new(walk(&mut *node.lhs.clone().unwrap(), prog).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.rhs.clone().unwrap(), prog).clone()));
            node.ty = node.rhs.clone().unwrap().ty;
            return node;
        }
        NodeType::POST_INC | NodeType::POST_DEC => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            node.ty = node.expr.clone().unwrap().ty;
            return node;
        }
        NodeType::EXCLAM | NodeType::NOT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            check_int(&*node.expr.clone().unwrap());
            node.ty = Rc::new(RefCell::new(int_ty()));
            return node;
        }
        NodeType::ADDR => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            check_lval(node.expr.clone().unwrap());
            node.ty = Rc::new(RefCell::new(ptr_to(node.expr.clone().unwrap().ty)));
            return node;
        }
        NodeType::DEREF => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));

            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.borrow().ty != CType::PTR {
                        bad_node!(node, format!("operand must be a pointer: {:?}", expr));
                    }

                    let ptr = expr.ty.borrow().ptr_to.clone().unwrap();
                    if ptr.borrow().ty == CType::VOID {
                        bad_node!(node, "operand dereference void pointer");
                    }
                }
                None => {}
            }

            let ty_tmp = node.expr.clone().unwrap().ty;
            node.ty = ty_tmp.borrow().clone().ptr_to.unwrap();
            return maybe_decay(node, decay);
        }
        NodeType::RETURN |
            NodeType::EXPR_STMT => {
            node.expr = Some(Box::new(walk(&mut *node.expr.clone().unwrap(), prog).clone()));
            return node;
        }
        NodeType::CALL => {
            for i in 0..node.args.len() {
                node.args[i] = walk(&mut node.args[i], prog).clone();
            }
            let node_ty = *node.ty.borrow().clone().returning.unwrap();
            node.ty = Rc::new(RefCell::new(node_ty));
            return node;
        }
        NodeType::COMP_STMT => {
            for i in 0..node.stmts.len() {
                node.stmts[i] = walk(&mut node.stmts[i], prog).clone();
            }
            return node;
        }
        NodeType::STMT_EXPR => {
            let mut body = walk(&mut *node.body.clone().unwrap(), prog).clone();

            if body.stmts.len() == 0 {
                bad_node!(node, "empty statement expression");
            }

            let n = body.stmts.pop().unwrap();
            if n.op != NodeType::EXPR_STMT {
                bad_node!(node, "statement expression returning void");
            }

            node.body = Some(Box::new(body));
            node.expr = n.expr.clone();
            node.ty = n.expr.clone().unwrap().ty;
            return node;
        }
        _ => {
            panic!("unknown node type: {:?}", node);
        }
    }
}

pub fn get_type(node: &mut Node) -> Type {
    let mut prog = new_program();
    return walk_nodecay(node, &mut prog).ty.borrow().clone();
}

pub fn sema(prog: &mut Program) {
    let mut funcs = prog.funcs.clone();

    for func in funcs.iter_mut() {
        let node = func.node.clone();
        if node.borrow().op == NodeType::DECL {
            continue;
        }

        assert!(node.borrow().op == NodeType::FUNC);

        let mut args = Vec::new();
        for a in node.borrow_mut().args.iter_mut() {
            args.push(walk(&mut a.clone(), prog).clone());
        }
        node.borrow_mut().args = args;

        let mut body = node.borrow_mut().body.clone().unwrap();
        node.borrow_mut().body = Some(Box::new(walk(&mut body, prog).clone()));

        let mut off = 0;
        for v in func.lvars.iter_mut() {
            off = roundup(off, v.borrow().ty.align);
            off += v.borrow().ty.size;
            v.borrow_mut().offset = off;
        }
        func.stacksize = off;
    }

    prog.funcs = funcs;
}
<|endoftext|>