<commit_before>use std::io::Write;
use diesel::expression::{AsExpression, Expression};
use diesel::pg::Pg;
use diesel::serialize::{self, IsNull, Output, ToSql};
use diesel::deserialize::{self, FromSql};
use diesel::sql_types::Cidr;
use crate::{IpNetwork, Ipv4Network, Ipv6Network};
use crate::postgres_common;

impl FromSql<Cidr, Pg> for Ipv4Network {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        postgres_common::from_sql_ipv4_network(bytes)
    }
}

impl FromSql<Cidr, Pg> for Ipv6Network {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        postgres_common::from_sql_ipv6_network(bytes)
    }
}

impl FromSql<Cidr, Pg> for IpNetwork {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        match bytes[0] {
            postgres_common::IPV4_TYPE => Ok(IpNetwork::V4(
                postgres_common::from_sql_ipv4_network(bytes)?,
            )),
            postgres_common::IPV6_TYPE => Ok(IpNetwork::V6(
                postgres_common::from_sql_ipv6_network(bytes)?,
            )),
            _ => Err("CIDR is not IP version 4 or 6".into()),
        }
    }
}

impl ToSql<Cidr, Pg> for Ipv4Network {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        let data = postgres_common::to_sql_ipv4_network(*self);
        out.write_all(&data).map(|_| IsNull::No).map_err(Into::into)
    }
}

impl ToSql<Cidr, Pg> for Ipv6Network {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        let data = postgres_common::to_sql_ipv6_network(*self);
        out.write_all(&data).map(|_| IsNull::No).map_err(Into::into)
    }
}

impl ToSql<Cidr, Pg> for IpNetwork {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        match self {
            IpNetwork::V4(network) => ToSql::<Cidr, Pg>::to_sql(network, out),
            IpNetwork::V6(network) => ToSql::<Cidr, Pg>::to_sql(network, out),
        }
    }
}

#[allow(dead_code)]
mod foreign_derives {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct IpNetworkProxy(IpNetwork);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct Ipv4NetworkProxy(Ipv4Network);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct Ipv6NetworkProxy(Ipv6Network);
}

diesel_infix_operator!(IsContainedBy, " << ", backend: Pg);
diesel_infix_operator!(IsContainedByOrEquals, " <<= ", backend: Pg);
diesel_infix_operator!(Contains, " >> ", backend: Pg);
diesel_infix_operator!(ContainsOrEquals, " >>= ", backend: Pg);
diesel_infix_operator!(ContainsOrIsContainedBy, " && ", backend: Pg);

/// Support for PostgreSQL Network Address Operators for Diesel
///
/// See [PostgreSQL documentation for details](https://www.postgresql.org/docs/current/static/functions-net.html).
pub trait PqCidrExtensionMethods: Expression<SqlType = Cidr> + Sized {
    /// Creates a SQL `<<` expression.
    fn is_contained_by<T>(self, other: T) -> IsContainedBy<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        IsContainedBy::new(self, other.as_expression())
    }

    /// Creates a SQL `<<=` expression.
    fn is_contained_by_or_equals<T>(self, other: T) -> IsContainedByOrEquals<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        IsContainedByOrEquals::new(self, other.as_expression())
    }

    /// Creates a SQL `>>` expression.
    fn contains<T>(self, other: T) -> Contains<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        Contains::new(self, other.as_expression())
    }

    /// Creates a SQL `>>=` expression.
    fn contains_or_equals<T>(self, other: T) -> ContainsOrEquals<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        ContainsOrEquals::new(self, other.as_expression())
    }

    /// Creates a SQL `&&` expression.
    fn contains_or_is_contained_by<T>(
        self,
        other: T,
    ) -> ContainsOrIsContainedBy<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        ContainsOrIsContainedBy::new(self, other.as_expression())
    }
}

impl<T> PqCidrExtensionMethods for T where T: Expression<SqlType = Cidr> {}

/// CIDR functions.
pub mod functions {
    use diesel::sql_types::Cidr;

    sql_function! {
        /// Extract family of address; 4 for IPv4, 6 for IPv6.
        fn family(x: Cidr) -> Integer;
    }
    sql_function! {
        /// Extract netmask length.
        fn masklen(x: Cidr) -> Integer;
    }
}

pub mod helper_types {
    pub type Family<Expr> = super::functions::family::HelperType<Expr>;
    pub type Masklen<Expr> = super::functions::masklen::HelperType<Expr>;
}

pub mod dsl {
    pub use super::functions::*;
    pub use super::helper_types::*;
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use diesel::sql_types::Cidr;
    use diesel::pg::Pg;
    use diesel::serialize::{Output, ToSql};
    use diesel::deserialize::FromSql;
    use diesel::prelude::*;
    use diesel::debug_query;
    use super::PqCidrExtensionMethods;
    use super::{IpNetwork, Ipv4Network, Ipv6Network};
    use super::dsl::*;

    table! {
        test {
            id -> Integer,
            ip_network -> Cidr,
            ipv4_network -> Cidr,
            ipv6_network -> Cidr,
        }
    }

    #[derive(Insertable)]
    #[table_name = "test"]
    pub struct NewPost {
        pub id: i32,
        pub ip_network: IpNetwork,
        pub ipv4_network: Ipv4Network,
        pub ipv6_network: Ipv6Network,
    }

    fn test_output() -> Output<'static, Vec<u8>, Pg> {
        use std::mem;
        Output::new(Vec::new(), unsafe { mem::uninitialized() })
    }

    #[test]
    fn ipv4_network() {
        let mut bytes = test_output();
        let ipv4_network = Ipv4Network::new(Ipv4Addr::new(1, 2, 3, 4), 32).unwrap();
        ToSql::<Cidr, Pg>::to_sql(&ipv4_network, &mut bytes).unwrap();
        let converted: Ipv4Network = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ipv4_network, converted);
    }

    #[test]
    fn ipv6_network() {
        let mut bytes = test_output();
        let ipv6_network = Ipv6Network::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap();
        ToSql::<Cidr, Pg>::to_sql(&ipv6_network, &mut bytes).unwrap();
        let converted: Ipv6Network = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ipv6_network, converted);
    }

    #[test]
    fn ip_network() {
        let mut bytes = test_output();
        let ip_network =
            IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap());
        ToSql::<Cidr, Pg>::to_sql(&ip_network, &mut bytes).unwrap();
        let converted: IpNetwork = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ip_network, converted);
    }

    #[test]
    fn operators() {
        let ip = IpNetwork::new(Ipv4Addr::new(127, 0, 0, 1), 32).unwrap();
        test::ip_network.is_contained_by(&ip);
        test::ip_network.is_contained_by_or_equals(&ip);
        test::ip_network.contains(&ip);
        test::ip_network.contains_or_equals(&ip);
        test::ip_network.contains_or_is_contained_by(&ip);
    }

    #[test]
    fn function_family() {
        let query = test::table.select(family(test::ip_network));
        let string_query = debug_query::<Pg, _>(&query).to_string();
        assert_eq!(
            "SELECT family(\"test\".\"ip_network\") FROM \"test\" -- binds: []",
            string_query
        );
    }

    #[test]
    fn function_masklen() {
        let query = test::table.select(masklen(test::ip_network));
        let string_query = debug_query::<Pg, _>(&query).to_string();
        assert_eq!(
            "SELECT masklen(\"test\".\"ip_network\") FROM \"test\" -- binds: []",
            string_query
        );
    }
}
<commit_msg>Fix diesel support test<commit_after>use std::io::Write;
use diesel::expression::{AsExpression, Expression};
use diesel::pg::Pg;
use diesel::serialize::{self, IsNull, Output, ToSql};
use diesel::deserialize::{self, FromSql};
use diesel::sql_types::Cidr;
use crate::{IpNetwork, Ipv4Network, Ipv6Network};
use crate::postgres_common;

impl FromSql<Cidr, Pg> for Ipv4Network {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        postgres_common::from_sql_ipv4_network(bytes)
    }
}

impl FromSql<Cidr, Pg> for Ipv6Network {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        postgres_common::from_sql_ipv6_network(bytes)
    }
}

impl FromSql<Cidr, Pg> for IpNetwork {
    fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        match bytes[0] {
            postgres_common::IPV4_TYPE => Ok(IpNetwork::V4(
                postgres_common::from_sql_ipv4_network(bytes)?,
            )),
            postgres_common::IPV6_TYPE => Ok(IpNetwork::V6(
                postgres_common::from_sql_ipv6_network(bytes)?,
            )),
            _ => Err("CIDR is not IP version 4 or 6".into()),
        }
    }
}

impl ToSql<Cidr, Pg> for Ipv4Network {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        let data = postgres_common::to_sql_ipv4_network(*self);
        out.write_all(&data).map(|_| IsNull::No).map_err(Into::into)
    }
}

impl ToSql<Cidr, Pg> for Ipv6Network {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        let data = postgres_common::to_sql_ipv6_network(*self);
        out.write_all(&data).map(|_| IsNull::No).map_err(Into::into)
    }
}

impl ToSql<Cidr, Pg> for IpNetwork {
    fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
        match self {
            IpNetwork::V4(network) => ToSql::<Cidr, Pg>::to_sql(network, out),
            IpNetwork::V6(network) => ToSql::<Cidr, Pg>::to_sql(network, out),
        }
    }
}

#[allow(dead_code)]
mod foreign_derives {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct IpNetworkProxy(IpNetwork);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct Ipv4NetworkProxy(Ipv4Network);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Cidr"]
    struct Ipv6NetworkProxy(Ipv6Network);
}

diesel_infix_operator!(IsContainedBy, " << ", backend: Pg);
diesel_infix_operator!(IsContainedByOrEquals, " <<= ", backend: Pg);
diesel_infix_operator!(Contains, " >> ", backend: Pg);
diesel_infix_operator!(ContainsOrEquals, " >>= ", backend: Pg);
diesel_infix_operator!(ContainsOrIsContainedBy, " && ", backend: Pg);

/// Support for PostgreSQL Network Address Operators for Diesel
///
/// See [PostgreSQL documentation for details](https://www.postgresql.org/docs/current/static/functions-net.html).
pub trait PqCidrExtensionMethods: Expression<SqlType = Cidr> + Sized {
    /// Creates a SQL `<<` expression.
    fn is_contained_by<T>(self, other: T) -> IsContainedBy<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        IsContainedBy::new(self, other.as_expression())
    }

    /// Creates a SQL `<<=` expression.
    fn is_contained_by_or_equals<T>(self, other: T) -> IsContainedByOrEquals<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        IsContainedByOrEquals::new(self, other.as_expression())
    }

    /// Creates a SQL `>>` expression.
    fn contains<T>(self, other: T) -> Contains<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        Contains::new(self, other.as_expression())
    }

    /// Creates a SQL `>>=` expression.
    fn contains_or_equals<T>(self, other: T) -> ContainsOrEquals<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        ContainsOrEquals::new(self, other.as_expression())
    }

    /// Creates a SQL `&&` expression.
    fn contains_or_is_contained_by<T>(
        self,
        other: T,
    ) -> ContainsOrIsContainedBy<Self, T::Expression>
    where
        T: AsExpression<Self::SqlType>,
    {
        ContainsOrIsContainedBy::new(self, other.as_expression())
    }
}

impl<T> PqCidrExtensionMethods for T where T: Expression<SqlType = Cidr> {}

/// CIDR functions.
pub mod functions {
    use diesel::sql_types::Cidr;

    sql_function! {
        /// Extract family of address; 4 for IPv4, 6 for IPv6.
        fn family(x: Cidr) -> Integer;
    }
    sql_function! {
        /// Extract netmask length.
        fn masklen(x: Cidr) -> Integer;
    }
}

pub mod helper_types {
    pub type Family<Expr> = super::functions::family::HelperType<Expr>;
    pub type Masklen<Expr> = super::functions::masklen::HelperType<Expr>;
}

pub mod dsl {
    pub use super::functions::*;
    pub use super::helper_types::*;
}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use diesel::sql_types::Cidr;
    use diesel::pg::Pg;
    use diesel::serialize::{Output, ToSql};
    use diesel::deserialize::FromSql;
    use diesel::prelude::*;
    use diesel::debug_query;
    use super::PqCidrExtensionMethods;
    use super::{IpNetwork, Ipv4Network, Ipv6Network};
    use super::dsl::*;

    table! {
        test {
            id -> Integer,
            ip_network -> Cidr,
            ipv4_network -> Cidr,
            ipv6_network -> Cidr,
        }
    }

    #[derive(Insertable)]
    #[table_name = "test"]
    pub struct NewPost {
        pub id: i32,
        pub ip_network: IpNetwork,
        pub ipv4_network: Ipv4Network,
        pub ipv6_network: Ipv6Network,
    }

    fn test_output() -> Output<'static, Vec<u8>, Pg> {
        let uninit = std::mem::MaybeUninit::uninit();
        let fake_metadata_lookup = unsafe { uninit.assume_init() };
        Output::new(Vec::new(), fake_metadata_lookup)
    }

    #[test]
    fn ipv4_network() {
        let mut bytes = test_output();
        let ipv4_network = Ipv4Network::new(Ipv4Addr::new(1, 2, 3, 4), 32).unwrap();
        ToSql::<Cidr, Pg>::to_sql(&ipv4_network, &mut bytes).unwrap();
        let converted: Ipv4Network = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ipv4_network, converted);
    }

    #[test]
    fn ipv6_network() {
        let mut bytes = test_output();
        let ipv6_network = Ipv6Network::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap();
        ToSql::<Cidr, Pg>::to_sql(&ipv6_network, &mut bytes).unwrap();
        let converted: Ipv6Network = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ipv6_network, converted);
    }

    #[test]
    fn ip_network() {
        let mut bytes = test_output();
        let ip_network =
            IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 128).unwrap());
        ToSql::<Cidr, Pg>::to_sql(&ip_network, &mut bytes).unwrap();
        let converted: IpNetwork = FromSql::<Cidr, Pg>::from_sql(Some(bytes.as_ref())).unwrap();
        assert_eq!(ip_network, converted);
    }

    #[test]
    fn operators() {
        let ip = IpNetwork::new(Ipv4Addr::new(127, 0, 0, 1), 32).unwrap();
        test::ip_network.is_contained_by(&ip);
        test::ip_network.is_contained_by_or_equals(&ip);
        test::ip_network.contains(&ip);
        test::ip_network.contains_or_equals(&ip);
        test::ip_network.contains_or_is_contained_by(&ip);
    }

    #[test]
    fn function_family() {
        let query = test::table.select(family(test::ip_network));
        let string_query = debug_query::<Pg, _>(&query).to_string();
        assert_eq!(
            "SELECT family(\"test\".\"ip_network\") FROM \"test\" -- binds: []",
            string_query
        );
    }

    #[test]
    fn function_masklen() {
        let query = test::table.select(masklen(test::ip_network));
        let string_query = debug_query::<Pg, _>(&query).to_string();
        assert_eq!(
            "SELECT masklen(\"test\".\"ip_network\") FROM \"test\" -- binds: []",
            string_query
        );
    }
}
<|endoftext|>


<commit_before>mod cp_multiplier;

pub struct Level {
    val: f64,
}

const MIN_LEVEL: f64 = 1.;
const MAX_LEVEL: f64 = 40.;

impl Level {
    pub fn new(val: f64) -> Option<Level> {
        if val < MIN_LEVEL || val > MAX_LEVEL || (val.fract() != 0.5f64 && val.fract() != 0.0f64) {
            return None;
        }

        Some(Level { val })
    }

    pub fn value(&self) -> f64 {
        self.val
    }

    pub fn cp_multiplier(&self) -> f64 {
        let &(_, cp_multiplier) = cp_multiplier::CP_MULTIPLIER
            .iter()
            .find(|&&(level, _)| level == self.value())
            .unwrap();

        cp_multiplier
    }

    pub fn min() -> Level {
        Level { val: MIN_LEVEL }
    }

    pub fn max() -> Level {
        Level { val: MAX_LEVEL }
    }
}

#[cfg(test)]
mod tests {
    use Level;

    #[test]
    fn level_construction() {
        let good = Level::new(34.5).unwrap();
        assert_eq!(34.5, good.value());

        let too_low = Level::new(0.5);
        assert!(too_low.is_none());

        let too_high = Level::new(40.5);
        assert!(too_high.is_none());

        let wrong_fractional = Level::new(11.1);
        assert!(wrong_fractional.is_none());
    }

    #[test]
    fn cp_multiplier() {
        let level = Level::new(10.).unwrap();
        assert_eq!(0.42250001, level.cp_multiplier());

        let level = Level::new(37.5).unwrap();
        assert_eq!(0.776064962, level.cp_multiplier());
    }
}
<commit_msg>Change max level to 39<commit_after>mod cp_multiplier;

pub struct Level {
    val: f64,
}

const MIN_LEVEL: f64 = 1.;
const MAX_LEVEL: f64 = 39.;

impl Level {
    pub fn new(val: f64) -> Option<Level> {
        if val < MIN_LEVEL || val > MAX_LEVEL || (val.fract() != 0.5f64 && val.fract() != 0.0f64) {
            return None;
        }

        Some(Level { val })
    }

    pub fn value(&self) -> f64 {
        self.val
    }

    pub fn cp_multiplier(&self) -> f64 {
        let &(_, cp_multiplier) = cp_multiplier::CP_MULTIPLIER
            .iter()
            .find(|&&(level, _)| level == self.value())
            .unwrap();

        cp_multiplier
    }

    pub fn min() -> Level {
        Level { val: MIN_LEVEL }
    }

    pub fn max() -> Level {
        Level { val: MAX_LEVEL }
    }
}

#[cfg(test)]
mod tests {
    use Level;

    #[test]
    fn level_construction() {
        let good = Level::new(34.5).unwrap();
        assert_eq!(34.5, good.value());

        let too_low = Level::new(0.5);
        assert!(too_low.is_none());

        let too_high = Level::new(40.5);
        assert!(too_high.is_none());

        let wrong_fractional = Level::new(11.1);
        assert!(wrong_fractional.is_none());
    }

    #[test]
    fn cp_multiplier() {
        let level = Level::new(10.).unwrap();
        assert_eq!(0.42250001, level.cp_multiplier());

        let level = Level::new(37.5).unwrap();
        assert_eq!(0.776064962, level.cp_multiplier());
    }
}
<|endoftext|>


<commit_before>//! Processor
//!
//! ## Terminololgy
//! * Evaluator - a code fragment to evaluate an expression
//! * Processor - A list of evaluators
//!
//! ## Phases for Generation
//!

use std::convert::From;
use std::rc::Rc;

use common::err::{Error, Result, Void, void_ok};
use common::func::{
	NoArgFn,
	UnaryFn,
	BinaryFn,
	TrinityFn
};
use common::plugin::{
	FuncRegistry,
	TypeRegistry
};
use common::rows::{
	MiniPage,
  FMiniPage,
	Page,
	OwnedPageBuilder,
	PageId
};
use common::session::Session;
use common::types::{Ty, name};

use jit::{JitCompiler};
use jit::builder::{Builder, CastOp};
use jit::types::{self, LLVMTy};
use jit::value::{Function, Predicate, Value, ValueRef, ToValue};
use plan::expr::*;
use plan::expr::visitor::{accept_by_default, Visitor};

use driver::DriverContext;
use super::NamedSchema;

#[repr(C)]
pub struct MiniPage2 {
  ptr: *const u8,
  size: usize
}

pub type MapFunc = extern "C" fn(&mut MiniPage2) -> i32;

macro_rules! unary_codegen (
  ($name:ident, $func:ident) => (
    pub fn $name(&mut self, expr: &Expr)
    {
      let val = self.visit(expr);
      let builder = &self.builder;

      self.stack.push(builder.$func(&val));
    }
  );
);

macro_rules! bin_codegen (
  ($name:ident, $func:ident) => (
    pub fn $name(&mut self, lhs: &Expr, rhs: &Expr)
    {
      println!("before lhs");
      let lhs_val = self.visit(lhs);
      println!("before rhs");
      let rhs_val = self.visit(rhs);
      let builder = &self.builder;

      self.stack.push(builder.$func(&lhs_val, &rhs_val));
    }
  );
);

fn to_llvm_ty<'a>(jit: &'a JitCompiler, ty: &Ty) -> &'a types::Ty
{
  match *ty {
    Ty::Bool => jit.get_void_ty(),
    Ty::I8   => jit.get_void_ty(),
    Ty::I16  => jit.get_void_ty(),
    Ty::I32  => jit.get_void_ty(),
    Ty::I64  => jit.get_void_ty(),
    Ty::F32  => jit.get_void_ty(),
    Ty::F64  => jit.get_void_ty(),
    _        => panic!("not supported type: {}", ty.base())
  }
}

pub struct ExprCompiler<'a>
{
  jit  : &'a JitCompiler,
  types: &'a Vec<Ty>,
	names: &'a Vec<&'a str>,
	stack: Vec<Value>,
  error: Option<Error>,
  func: Function,
  builder: Builder
}

impl<'a> ExprCompiler<'a> {
  fn new(jit: &'a JitCompiler,
         fn_registry: &FuncRegistry,
		     session: &Session,
		     schema : &'a NamedSchema,) -> ExprCompiler<'a> {
    let builder = jit.new_builder();
    let func = ExprCompiler::generate_fn_prototype(jit, &builder);

		ExprCompiler {
      jit   : jit,
			types : &schema.types,
			names : &schema.names,
			stack : Vec::new(),
			error : None,
      func: func,
      builder: builder
		}
	}

  pub fn compile2(&mut self, expr: &Expr) -> Result<Value>
  {
    self.accept(expr);
    match self.stack.pop() {
      Some(v) => Ok(v),
      None    => Err(Error::CorruptedFunction("empty value stack".to_string()))
    }
  }

  pub fn compile(
            jit: &'a JitCompiler,
						fn_registry: &FuncRegistry,
		        session    : &'a Session,
					  schema     : &'a NamedSchema,
					  expr       : &Expr) -> Result<Rc<MapFunc>>
	{
    let mut map = ExprCompiler::new(jit, fn_registry, session, schema);
    println!("before accept");
    map.accept(expr);
    println!("after accept");
    ExprCompiler::generate_scalar_func(&mut map, jit);
    println!("after generate_scalar_func");
    map.ret_func(jit)
  }

  fn generate_fn_prototype(jit: &JitCompiler, bld: &Builder) -> Function {
    let minipage_ty = jit.get_ty("struct.MiniPage").unwrap();
    let minipage_ptr_ty = jit.get_pointer_ty(&minipage_ty);
    jit.create_func_prototype(
      "processor",
      &i32::llvm_ty(jit.context()),
      &[&minipage_ptr_ty],
      Some(bld))
  }

  fn generate_scalar_func(map: &mut ExprCompiler, jit: &JitCompiler) {
    let func = &map.func;
    let builder = &map.builder;

    let codegen = map.stack.pop().unwrap();
    let minipage: Value = func.arg(0).into();

    let call = match jit.get_func("test") {
      Some(f) => {
        builder.create_call(&f, &[&minipage, &codegen])
      },
      _       => panic!("No such a function")
    };
    builder.create_ret(&call);
  }

  fn ret_func(&self, jit: &JitCompiler) -> Result<Rc<MapFunc>>
  {
    // dump code
    jit.dump();

    match jit.verify() {
      Ok(_) => {
        let func_ptr = unsafe { jit.get_func_ptr(&self.func).unwrap() };
        let func: MapFunc = unsafe {::std::mem::transmute(func_ptr)};
        Ok(Rc::new(func))
      }
      Err(msg) => {
        error!("{}", msg);
        Err(Error::CorruptedFunction(msg.to_owned()))
      }
    }
  }

  #[inline(always)]
  fn visit(&mut self, expr: &Expr) -> Value
  {
    self.accept(expr);
    // Stack must contain at least one Value item.
    // Otherwise, it is definitely a bug.
    self.stack.pop().unwrap()
  }

  #[inline(always)]
  fn push_value<T: ToValue>(&mut self, val: &T)
  {
    let v = val.to_value(self.jit.context());
    self.stack.push(v);
  }

  unary_codegen!(Not, create_not);

	pub fn IsNull(&self, c: &Expr)
	{
	}

	pub fn IsNotNull(&self, e: &Expr)
	{
	}

	pub fn PlusSign(&mut self, e: &Expr)
	{
    self.accept(e);
	}

  unary_codegen!(MinusSign, create_neg);

	pub fn Cast(&mut self, e: &Expr, from: &Ty, to: &Ty)
	{
    // if the both types are equivalent, just return.
    if from == to { return; }

    let cast_op = if from.is_sint() && to.is_sint() {
      if from.size_of() < to.size_of() {
        CastOp::SExt
      } else {
        CastOp::Trunc
      }
    } else if from.is_sint() && to.is_float() {
      CastOp::SIToFP
    } else if from.is_uint() && to.is_float() {
      CastOp::UIToFP
    } else if from.is_float() && to.is_sint() {
      CastOp::FPToSI
    } else if from.is_float() && to.is_uint() {
      CastOp::FPToUI
    } else if from.is_float() && to.is_float() {
      if from.size_of() < to.size_of() {
        CastOp::FPExt
      } else {
        CastOp::FPTrunc
      }
    } else {
      panic!("not supported cast from {} to {}", from.base(), to.base());
    };

    let val = self.visit(e);
    let builder = &self.builder;

    self.stack.push(builder.create_cast(cast_op, &val, to_llvm_ty(self.jit, to)));
	}

  bin_codegen!(And, create_and);
  bin_codegen!(Or,  create_or);
  bin_codegen!(Xor, create_xor);

	pub fn Cmp(&mut self, op: &CmpOp, lhs: &Expr, rhs: &Expr)
	{
    let lhs_val = self.visit(lhs);
    let rhs_val = self.visit(rhs);

    let builder = &self.builder;

    let pred = match *op {
      CmpOp::Eq => Predicate::Eq,
      CmpOp::Ne => Predicate::Ne,
      CmpOp::Lt => Predicate::Lt,
      CmpOp::Le => Predicate::Le,
      CmpOp::Gt => Predicate::Gt,
      CmpOp::Ge => Predicate::Ge
    };

    self.stack.push(builder.create_cmp(&lhs_val, &rhs_val, pred));
	}

	pub fn Arithm(&mut self, ty: &Ty, op: &ArithmOp, lhs: &Expr, rhs: &Expr)
	{
    let lhs_val = self.visit(lhs);
    let rhs_val = self.visit(rhs);

    let builder = &self.builder;

    self.stack.push(match *op {
      ArithmOp::Plus => {builder.create_add(&lhs_val, &rhs_val)}
      ArithmOp::Sub  => {builder.create_sub(&lhs_val, &rhs_val)}
      ArithmOp::Mul  => {builder.create_mul(&lhs_val, &rhs_val)}
      ArithmOp::Div  => {builder.create_div(&lhs_val, &rhs_val)}
      ArithmOp::Rem  => {builder.create_rem(&lhs_val, &rhs_val)}
    });
	}

	pub fn Func(&self, f: &FnDecl, args: &Vec<Box<Expr>>)
	{
	}

  pub fn Const(&mut self, l: &Literal)
  {
    match *l {
      Literal::U8(ref v)  => self.push_value(v),
      Literal::I8(ref v)  => self.push_value(v),
      Literal::I16(ref v) => self.push_value(v),
      Literal::I32(ref v) => self.push_value(v),
      Literal::I64(ref v) => self.push_value(v),
      Literal::F32(ref v) => self.push_value(v),
      Literal::F64(ref v) => self.push_value(v),
      _                    => unimplemented!()
    }
  }

	pub fn Field(&mut self, ty: &Ty, name: &str)
	{
		/*
    let found: Option<(usize, &Ty, &&str)>;

		found = izip!(0 .. self.types.len(), self.types, self.names)
						.find(|&(i, t, n)| *n == name);

    let eval = match found {
    	Some(f) => FieldEvaluator {idx: f.0, ty: f.1.clone()},
    	None    => panic!("no such field for {}", name)
    };*/
	}
}

impl<'a> visitor::Visitor for ExprCompiler<'a>
{
	fn accept(&mut self, e: &Expr)
	{
	  match *e.kind() {
	    ExprKind::Not      (ref c)               => self.Not(c),
	    ExprKind::IsNull   (ref c)               => self.IsNull(c),
	    ExprKind::IsNotNull(ref c)               => self.IsNotNull(c),
	    ExprKind::PlusSign (ref c)               => self.PlusSign(c),
	    ExprKind::MinusSign(ref c)               => self.MinusSign(c),
	    ExprKind::Cast     (ref c, ref f, ref t) => self.Cast(c, f, t),

	    ExprKind::And      (ref l, ref r)        => self.And(l, r),
	    ExprKind::Or       (ref l, ref r)        => self.Or(l, r),
	    ExprKind::Cmp      (ref o, ref l, ref r) => self.Cmp(o, l, r),
	    ExprKind::Arithm   (ref o, ref l, ref r) => self.Arithm(e.ty(), o, l, r),

	    ExprKind::Fn     (ref f, ref args)  => self.Func(f, args),
			ExprKind::Field  (ref name)         => self.Field(e.ty(), name),
	    ExprKind::Const  (ref lit)          => self.Const(lit),
	    /*
	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },*/
	    _ => panic!("")
	  }
	}
}

pub trait Processor
{
  fn process(
    &self,
    input: &Page,
    builder: &mut OwnedPageBuilder) -> Void;
}

#[cfg(test)]
mod tests {
	use common::rows::{
		Page,
		OwnedPageBuilder,
		PageId
	};
	use common::plugin::*;
	use common::session::Session;
	use common::storage::{RandomTable, MemTable};
	use common::types::*;

  use jit::JitCompiler;

	use plan::expr::*;
	use driver::DriverContext;

	use super::super::NamedSchema;

	use super::*;

  #[test]
  pub fn codegen() {
    let plugin_mgr = PluginManager::new();
    let jit = JitCompiler::new_from_bc("../common/target/ir/common.bc").ok().unwrap();
    assert!(jit.get_ty("struct.MiniPage").is_some());
    assert!(jit.get_ty("struct.Page").is_some());

    let types: Vec<Ty> = schema!(
	    I64, // l_orderkey      bigint
	    I64, // l_partkey       bigint
	    I64, // l_suppkey       bigint
	    I32, // l_linenumber    int
	    F64, // l_quantity      double,
	    F64, // l_extendedprice double,
	    F64, // l_discount      double,
	    F64  // l_tax           double,
	    // string types are not implmeneted yet.
    );

	  let names: Vec<&str> = vec![
	  	"l_orderkey",
	  	"l_partkey",
	  	"l_suppkey",
	  	"l_linenumber",
	  	"l_quantity",
	  	"l_extendedprice",
	  	"l_discount",
	  	"l_tax"
	  ];

    let expr = Plus(I32, Const(19800401i32), Const(1i32));
    //let expr = Or(Const(4i32), Const(2i32));
    //let expr = Not(Const(0i32));
    //let expr = MinusSign(Const(7i32));
    let schema  = NamedSchema::new(&names, &types);
  	let session = Session;

    let map = ExprCompiler::compile(&jit,
                                   plugin_mgr.fn_registry(),
																	 &session,
																	 &schema,
																	 &expr).ok().unwrap();

    let mut minipage = MiniPage2 {
      ptr: ::std::ptr::null(),
      size: 0
    };
    assert_eq!(map(&mut minipage), 19800401i32);
  }
}<commit_msg>Separate ExprCompiler from map function generation.<commit_after>//! Processor
//!
//! ## Terminololgy
//! * Evaluator - a code fragment to evaluate an expression
//! * Processor - A list of evaluators
//!
//! ## Phases for Generation
//!

use std::convert::From;
use std::rc::Rc;

use common::err::{Error, Result, Void, void_ok};
use common::func::{
	NoArgFn,
	UnaryFn,
	BinaryFn,
	TrinityFn
};
use common::plugin::{
	FuncRegistry,
	TypeRegistry
};
use common::rows::{
	MiniPage,
  FMiniPage,
	Page,
	OwnedPageBuilder,
	PageId
};
use common::session::Session;
use common::types::{Ty, name};

use jit::{JitCompiler};
use jit::builder::{Builder, CastOp};
use jit::types::{self, LLVMTy};
use jit::value::{Function, Predicate, Value, ValueRef, ToValue};
use plan::expr::*;
use plan::expr::visitor::{accept_by_default, Visitor};

use driver::DriverContext;
use super::NamedSchema;

#[repr(C)]
pub struct MiniPage2 {
  ptr: *const u8,
  size: usize
}

pub type MapFunc = extern "C" fn(&mut MiniPage2) -> i32;

macro_rules! unary_codegen (
  ($name:ident, $func:ident) => (
    pub fn $name(&mut self, expr: &Expr)
    {
      let val = self.visit(expr);
      let builder = &self.builder;

      self.stack.push(builder.$func(&val));
    }
  );
);

macro_rules! bin_codegen (
  ($name:ident, $func:ident) => (
    pub fn $name(&mut self, lhs: &Expr, rhs: &Expr)
    {
      println!("before lhs");
      let lhs_val = self.visit(lhs);
      println!("before rhs");
      let rhs_val = self.visit(rhs);
      let builder = &self.builder;

      self.stack.push(builder.$func(&lhs_val, &rhs_val));
    }
  );
);

fn to_llvm_ty<'a>(jit: &'a JitCompiler, ty: &Ty) -> &'a types::Ty
{
  match *ty {
    Ty::Bool => jit.get_void_ty(),
    Ty::I8   => jit.get_void_ty(),
    Ty::I16  => jit.get_void_ty(),
    Ty::I32  => jit.get_void_ty(),
    Ty::I64  => jit.get_void_ty(),
    Ty::F32  => jit.get_void_ty(),
    Ty::F64  => jit.get_void_ty(),
    _        => panic!("not supported type: {}", ty.base())
  }
}

pub fn compile_map(jit: &JitCompiler, fn_reg: &FuncRegistry, sess: &Session, schema: &NamedSchema, expr: &Expr) -> Result<Rc<MapFunc>> {
  let builder = jit.new_builder();
  let func = create_map_prototype(jit, &builder);

  let mut exprc = ExprCompiler::new(jit, fn_reg, sess, schema, &builder);
  let codegen = try!(exprc.compile2(expr));
  builder.create_ret(&codegen);
  // dump code
  jit.dump();
  ret_map_func(jit, &func)
}

fn create_map_prototype(jit: &JitCompiler, bld: &Builder) -> Function {
  let minipage_ty = jit.get_ty("struct.MiniPage").unwrap();
  let minipage_ptr_ty = jit.get_pointer_ty(&minipage_ty);
  jit.create_func_prototype(
    "processor",
    &i32::llvm_ty(jit.context()),
    &[&minipage_ptr_ty],
    Some(bld))
}

fn ret_map_func(jit: &JitCompiler, func: &Function) -> Result<Rc<MapFunc>> {
  match jit.verify() {
    Ok(_) => {
      let func_ptr = unsafe { jit.get_func_ptr(func).unwrap() };
      let func = unsafe {::std::mem::transmute(func_ptr)};
      Ok(Rc::new(func))
    }
    Err(msg) => {
      error!("{}", msg);
      Err(Error::CorruptedFunction(msg.to_owned()))
    }
  }
}

pub struct ExprCompiler<'a>
{
  jit  : &'a JitCompiler,
  types: &'a Vec<Ty>,
	names: &'a Vec<&'a str>,
	stack: Vec<Value>,
  error: Option<Error>,
  builder: &'a Builder
}

impl<'a> ExprCompiler<'a> {
  fn new(jit: &'a JitCompiler,
         fn_registry: &FuncRegistry,
		     session: &Session,
		     schema : &'a NamedSchema, builder: &'a Builder) -> ExprCompiler<'a> {
    //let builder = jit.new_builder();
    //let func = ExprCompiler::generate_fn_prototype(jit, &builder);

		ExprCompiler {
      jit   : jit,
			types : &schema.types,
			names : &schema.names,
			stack : Vec::new(),
			error : None,
      builder: builder
		}
	}

  pub fn compile2(&mut self, expr: &Expr) -> Result<Value>
  {
    self.accept(expr);
    match self.stack.pop() {
      Some(v) => Ok(v),
      None    => Err(Error::CorruptedFunction("empty value stack".to_string()))
    }
  }

  /*
  fn generate_scalar_func(map: &mut ExprCompiler, jit: &JitCompiler) {
    let func = &map.func;
    let builder = &map.builder;

    let codegen = map.stack.pop().unwrap();
    let minipage: Value = func.arg(0).into();

    let call = match jit.get_func("test") {
      Some(f) => {
        builder.create_call(&f, &[&minipage, &codegen])
      },
      _       => panic!("No such a function")
    };
    builder.create_ret(&call);
  }*/

  #[inline(always)]
  fn visit(&mut self, expr: &Expr) -> Value
  {
    self.accept(expr);
    // Stack must contain at least one Value item.
    // Otherwise, it is definitely a bug.
    self.stack.pop().unwrap()
  }

  #[inline(always)]
  fn push_value<T: ToValue>(&mut self, val: &T)
  {
    let v = val.to_value(self.jit.context());
    self.stack.push(v);
  }

  unary_codegen!(Not, create_not);

	pub fn IsNull(&self, c: &Expr)
	{
	}

	pub fn IsNotNull(&self, e: &Expr)
	{
	}

	pub fn PlusSign(&mut self, e: &Expr)
	{
    self.accept(e);
	}

  unary_codegen!(MinusSign, create_neg);

	pub fn Cast(&mut self, e: &Expr, from: &Ty, to: &Ty)
	{
    // if the both types are equivalent, just return.
    if from == to { return; }

    let cast_op = if from.is_sint() && to.is_sint() {
      if from.size_of() < to.size_of() {
        CastOp::SExt
      } else {
        CastOp::Trunc
      }
    } else if from.is_sint() && to.is_float() {
      CastOp::SIToFP
    } else if from.is_uint() && to.is_float() {
      CastOp::UIToFP
    } else if from.is_float() && to.is_sint() {
      CastOp::FPToSI
    } else if from.is_float() && to.is_uint() {
      CastOp::FPToUI
    } else if from.is_float() && to.is_float() {
      if from.size_of() < to.size_of() {
        CastOp::FPExt
      } else {
        CastOp::FPTrunc
      }
    } else {
      panic!("not supported cast from {} to {}", from.base(), to.base());
    };

    let val = self.visit(e);
    let builder = &self.builder;

    self.stack.push(builder.create_cast(cast_op, &val, to_llvm_ty(self.jit, to)));
	}

  bin_codegen!(And, create_and);
  bin_codegen!(Or,  create_or);
  bin_codegen!(Xor, create_xor);

	pub fn Cmp(&mut self, op: &CmpOp, lhs: &Expr, rhs: &Expr)
	{
    let lhs_val = self.visit(lhs);
    let rhs_val = self.visit(rhs);

    let builder = &self.builder;

    let pred = match *op {
      CmpOp::Eq => Predicate::Eq,
      CmpOp::Ne => Predicate::Ne,
      CmpOp::Lt => Predicate::Lt,
      CmpOp::Le => Predicate::Le,
      CmpOp::Gt => Predicate::Gt,
      CmpOp::Ge => Predicate::Ge
    };

    self.stack.push(builder.create_cmp(&lhs_val, &rhs_val, pred));
	}

	pub fn Arithm(&mut self, ty: &Ty, op: &ArithmOp, lhs: &Expr, rhs: &Expr)
	{
    let lhs_val = self.visit(lhs);
    let rhs_val = self.visit(rhs);

    let builder = &self.builder;

    self.stack.push(match *op {
      ArithmOp::Plus => {builder.create_add(&lhs_val, &rhs_val)}
      ArithmOp::Sub  => {builder.create_sub(&lhs_val, &rhs_val)}
      ArithmOp::Mul  => {builder.create_mul(&lhs_val, &rhs_val)}
      ArithmOp::Div  => {builder.create_div(&lhs_val, &rhs_val)}
      ArithmOp::Rem  => {builder.create_rem(&lhs_val, &rhs_val)}
    });
	}

	pub fn Func(&self, f: &FnDecl, args: &Vec<Box<Expr>>)
	{
	}

  pub fn Const(&mut self, l: &Literal)
  {
    match *l {
      Literal::U8(ref v)  => self.push_value(v),
      Literal::I8(ref v)  => self.push_value(v),
      Literal::I16(ref v) => self.push_value(v),
      Literal::I32(ref v) => self.push_value(v),
      Literal::I64(ref v) => self.push_value(v),
      Literal::F32(ref v) => self.push_value(v),
      Literal::F64(ref v) => self.push_value(v),
      _                    => unimplemented!()
    }
  }

	pub fn Field(&mut self, ty: &Ty, name: &str)
	{
		/*
    let found: Option<(usize, &Ty, &&str)>;

		found = izip!(0 .. self.types.len(), self.types, self.names)
						.find(|&(i, t, n)| *n == name);

    let eval = match found {
    	Some(f) => FieldEvaluator {idx: f.0, ty: f.1.clone()},
    	None    => panic!("no such field for {}", name)
    };*/
	}
}

impl<'a> visitor::Visitor for ExprCompiler<'a>
{
	fn accept(&mut self, e: &Expr)
	{
	  match *e.kind() {
	    ExprKind::Not      (ref c)               => self.Not(c),
	    ExprKind::IsNull   (ref c)               => self.IsNull(c),
	    ExprKind::IsNotNull(ref c)               => self.IsNotNull(c),
	    ExprKind::PlusSign (ref c)               => self.PlusSign(c),
	    ExprKind::MinusSign(ref c)               => self.MinusSign(c),
	    ExprKind::Cast     (ref c, ref f, ref t) => self.Cast(c, f, t),

	    ExprKind::And      (ref l, ref r)        => self.And(l, r),
	    ExprKind::Or       (ref l, ref r)        => self.Or(l, r),
	    ExprKind::Cmp      (ref o, ref l, ref r) => self.Cmp(o, l, r),
	    ExprKind::Arithm   (ref o, ref l, ref r) => self.Arithm(e.ty(), o, l, r),

	    ExprKind::Fn     (ref f, ref args)  => self.Func(f, args),
			ExprKind::Field  (ref name)         => self.Field(e.ty(), name),
	    ExprKind::Const  (ref lit)          => self.Const(lit),
	    /*
	    ExprKind::Switch(ref cases, ref default) => {
	    	for c in cases.iter() {
	    		v.accept(c);
	   	  }

	    	v.accept(default);
	    },

	    ExprKind::Case   (ref l, ref r) => { v.accept(l); v.accept(r) },*/
	    _ => panic!("")
	  }
	}
}

pub trait Processor
{
  fn process(
    &self,
    input: &Page,
    builder: &mut OwnedPageBuilder) -> Void;
}

#[cfg(test)]
mod tests {
	use common::rows::{
		Page,
		OwnedPageBuilder,
		PageId
	};
	use common::plugin::*;
	use common::session::Session;
	use common::storage::{RandomTable, MemTable};
	use common::types::*;

  use jit::JitCompiler;

	use plan::expr::*;
	use driver::DriverContext;

	use super::super::NamedSchema;

	use super::*;

  #[test]
  pub fn codegen() {
    let plugin_mgr = PluginManager::new();
    let jit = JitCompiler::new_from_bc("../common/target/ir/common.bc").ok().unwrap();
    assert!(jit.get_ty("struct.MiniPage").is_some());
    assert!(jit.get_ty("struct.Page").is_some());

    let types: Vec<Ty> = schema!(
	    I64, // l_orderkey      bigint
	    I64, // l_partkey       bigint
	    I64, // l_suppkey       bigint
	    I32, // l_linenumber    int
	    F64, // l_quantity      double,
	    F64, // l_extendedprice double,
	    F64, // l_discount      double,
	    F64  // l_tax           double,
	    // string types are not implmeneted yet.
    );

	  let names: Vec<&str> = vec![
	  	"l_orderkey",
	  	"l_partkey",
	  	"l_suppkey",
	  	"l_linenumber",
	  	"l_quantity",
	  	"l_extendedprice",
	  	"l_discount",
	  	"l_tax"
	  ];

    let expr = Plus(I32, Const(19800401i32), Const(1i32));
    //let expr = Or(Const(4i32), Const(2i32));
    //let expr = Not(Const(0i32));
    //let expr = MinusSign(Const(7i32));
    let schema  = NamedSchema::new(&names, &types);
  	let session = Session;

    // let map = ExprCompiler::compile(&jit,
    //                                plugin_mgr.fn_registry(),
		// 															 &session,
		// 															 &schema,
		// 															 &expr).ok().unwrap();
    let map = compile_map(&jit,
                          plugin_mgr.fn_registry(),
                          &session,
                          &schema,
                          &expr).ok().unwrap();

    let mut minipage = MiniPage2 {
      ptr: ::std::ptr::null(),
      size: 0
    };
    assert_eq!(map(&mut minipage), 19800401i32);
  }
}<|endoftext|>


<commit_before>#![allow(missing_doc)]

//! A First Person Shooter controller.

use std::num::{One, Zero};
use input::keyboard;
use {
    input,
    Camera,
    GameEvent,
    Input,
    Update,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// FPS controller settings.
pub struct FPSControllerSettings {
    /// Which key to press to move forward.
    pub move_forward_key: keyboard::Key,
    /// Which key to press to move backward.
    pub move_backward_key: keyboard::Key,
    /// Which key to press to strafe left.
    pub strafe_left_key: keyboard::Key,
    /// Which key to press to strafe right.
    pub strafe_right_key: keyboard::Key,
    /// Which key to press to fly up.
    pub fly_up_key: keyboard::Key,
    /// Which key to press to fly down.
    pub fly_down_key: keyboard::Key,
    /// Which key to press to move faster.
    pub move_faster_key: keyboard::Key,
}

impl FPSControllerSettings {
    /// Creates new FPS controller settings with defaults.
    pub fn default() -> FPSControllerSettings {
        FPSControllerSettings {
            move_forward_key: keyboard::W,
            move_backward_key: keyboard::S,
            strafe_left_key: keyboard::A,
            strafe_right_key: keyboard::D,
            fly_up_key: keyboard::Space,
            fly_down_key: keyboard::LShift,
            move_faster_key: keyboard::LCtrl,
        }
    }
}

/// Models a First Person Shooter (FPS) controller.
pub struct FPSController<T=f32> {
    /// The FPS controller settings.
    pub settings: FPSControllerSettings,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The keys that are pressed.
    pub keys: Keys,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FPSController<T> {
    /// Creates a new FPS controller.
    pub fn new(settings: FPSControllerSettings) -> FPSController<T> {
        let _0: T = Zero::zero();
        FPSController {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            velocity: One::one(),
        }
    }

    /// Handles game event and updates camera.
    pub fn event(&mut self, e: &GameEvent, camera: &mut Camera<T>) {
        let &FPSController {
            yaw: ref mut yaw,
            pitch: ref mut pitch,
            keys: ref mut keys,
            direction: ref mut direction,
            velocity: ref mut velocity,
            settings: ref settings,
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            Update(args) => {
                let dt: T = FromPrimitive::from_f64(args.dt).unwrap();
                let dh = dt * *velocity * _3;
                let [dx, dy, dz] = *direction;
                let (s, c) = (yaw.sin(), yaw.cos());
                camera.position = [
                    camera.position[0] + (s * dx - c * dz) * dh,
                    camera.position[1] + dy * dt * _4,
                    camera.position[2] + (s * dz + c * dx) * dh
                ];
            },
            Input(input::MouseRelativeMove(args)) => {
                let dx: T = FromPrimitive::from_f64(args.dx).unwrap();
                let dy: T = FromPrimitive::from_f64(args.dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
                camera.set_yaw_pitch(*yaw, *pitch);
            },
            Input(input::KeyPress(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match args.key {
                    x if x == settings.move_forward_key => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_key => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_key => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_key => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_key => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_key => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_key => *velocity = _2,
                    _ => {}
                }
            },
            Input(input::KeyRelease(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match args.key {
                    x if x == settings.move_forward_key => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_key => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_key => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_key => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_key => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_key => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_key => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<commit_msg>Using name matching on destructure<commit_after>#![allow(missing_doc)]

//! A First Person Shooter controller.

use std::num::{One, Zero};
use input::keyboard;
use {
    input,
    Camera,
    GameEvent,
    Input,
    Update,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// FPS controller settings.
pub struct FPSControllerSettings {
    /// Which key to press to move forward.
    pub move_forward_key: keyboard::Key,
    /// Which key to press to move backward.
    pub move_backward_key: keyboard::Key,
    /// Which key to press to strafe left.
    pub strafe_left_key: keyboard::Key,
    /// Which key to press to strafe right.
    pub strafe_right_key: keyboard::Key,
    /// Which key to press to fly up.
    pub fly_up_key: keyboard::Key,
    /// Which key to press to fly down.
    pub fly_down_key: keyboard::Key,
    /// Which key to press to move faster.
    pub move_faster_key: keyboard::Key,
}

impl FPSControllerSettings {
    /// Creates new FPS controller settings with defaults.
    pub fn default() -> FPSControllerSettings {
        FPSControllerSettings {
            move_forward_key: keyboard::W,
            move_backward_key: keyboard::S,
            strafe_left_key: keyboard::A,
            strafe_right_key: keyboard::D,
            fly_up_key: keyboard::Space,
            fly_down_key: keyboard::LShift,
            move_faster_key: keyboard::LCtrl,
        }
    }
}

/// Models a First Person Shooter (FPS) controller.
pub struct FPSController<T=f32> {
    /// The FPS controller settings.
    pub settings: FPSControllerSettings,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The keys that are pressed.
    pub keys: Keys,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FPSController<T> {
    /// Creates a new FPS controller.
    pub fn new(settings: FPSControllerSettings) -> FPSController<T> {
        let _0: T = Zero::zero();
        FPSController {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            velocity: One::one(),
        }
    }

    /// Handles game event and updates camera.
    pub fn event(&mut self, e: &GameEvent, camera: &mut Camera<T>) {
        let &FPSController {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            Update(args) => {
                let dt: T = FromPrimitive::from_f64(args.dt).unwrap();
                let dh = dt * *velocity * _3;
                let [dx, dy, dz] = *direction;
                let (s, c) = (yaw.sin(), yaw.cos());
                camera.position = [
                    camera.position[0] + (s * dx - c * dz) * dh,
                    camera.position[1] + dy * dt * _4,
                    camera.position[2] + (s * dz + c * dx) * dh
                ];
            },
            Input(input::MouseRelativeMove(args)) => {
                let dx: T = FromPrimitive::from_f64(args.dx).unwrap();
                let dy: T = FromPrimitive::from_f64(args.dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
                camera.set_yaw_pitch(*yaw, *pitch);
            },
            Input(input::KeyPress(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match args.key {
                    x if x == settings.move_forward_key => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_key => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_key => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_key => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_key => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_key => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_key => *velocity = _2,
                    _ => {}
                }
            },
            Input(input::KeyRelease(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match args.key {
                    x if x == settings.move_forward_key => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_key => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_key => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_key => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_key => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_key => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_key => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<|endoftext|>


<commit_before>#![cfg(test)]

use glib::translate::*;
use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::sync::Once;

#[cfg(have_pangoft2)]

/// Given a filename from `test_generator::test_resources`, computes the correct fixture filename.
///
/// The `test_resources` procedural macro works by running a filename glob starting on
/// the toplevel of the Cargo workspace.  However, when a test function gets run,
/// its $cwd is the test crate's toplevel.  This function fixes the pathname generated
/// by `test_resources` so that it has the correct path.
pub fn fixture_path(filename_from_test_resources: &str) -> PathBuf {
    let crate_toplevel = PathBuf::from(
        env::var_os("CARGO_MANIFEST_DIR")
            .expect(r#"CARGO_MANIFEST_DIR" is not set, please set it or run under "cargo test""#),
    );

    let workspace_toplevel = crate_toplevel.parent().unwrap();

    workspace_toplevel.join(filename_from_test_resources)
}

#[cfg(have_pangoft2)]
mod pango_ft2 {
    use super::*;
    use fontconfig_sys::fontconfig;
    use glib::prelude::*;
    use pangocairo::FontMap;

    extern "C" {
        // pango_fc_font_map_set_config (PangoFcFontMap *fcfontmap,
        //                               FcConfig       *fcconfig);
        // This is not bound in gtk-rs, and PangoFcFontMap is not even exposed, so we'll bind it by hand.
        fn pango_fc_font_map_set_config(
            font_map: *mut libc::c_void,
            config: *mut fontconfig::FcConfig,
        );
    }

    pub unsafe fn load_test_fonts() {
        let font_paths = [
            "tests/resources/Roboto-Regular.ttf",
            "tests/resources/Roboto-Italic.ttf",
            "tests/resources/Roboto-Bold.ttf",
            "tests/resources/Roboto-BoldItalic.ttf",
        ];

        let config = fontconfig::FcConfigCreate();

        for path in &font_paths {
            let path = fixture_path(path);
            let path_str = path.to_str().unwrap();
            let path_cstring = CString::new(path_str).unwrap();

            if fontconfig::FcConfigAppFontAddFile(config, path_cstring.as_ptr() as *const _) == 0 {
                panic!(
                    "Could not load font file {:?} for tests; aborting",
                    path_str
                );
            }
        }

        let font_map = FontMap::new_for_font_type(cairo::FontType::FontTypeFt).unwrap();
        let raw_font_map: *mut pango_sys::PangoFontMap = font_map.to_glib_none().0;

        pango_fc_font_map_set_config(raw_font_map as *mut _, config);
        fontconfig::FcConfigDestroy(config);

        FontMap::set_default(Some(font_map.downcast::<pangocairo::FontMap>().unwrap()));
    }
}

#[cfg(have_pangoft2)]
pub fn setup_font_map() {
    static ONCE: Once = Once::new();

    ONCE.call_once(|| unsafe {
        self::pango_ft2::load_test_fonts();
    });
}

#[cfg(not(have_pangoft2))]
pub fn setup_font_map() {}
<commit_msg>FontMap::set_default is per-thread, so don't do it in a Once<commit_after>#![cfg(test)]

use glib::translate::*;
use libc;
use std::env;
use std::ffi::CString;
use std::path::PathBuf;

#[cfg(have_pangoft2)]

/// Given a filename from `test_generator::test_resources`, computes the correct fixture filename.
///
/// The `test_resources` procedural macro works by running a filename glob starting on
/// the toplevel of the Cargo workspace.  However, when a test function gets run,
/// its $cwd is the test crate's toplevel.  This function fixes the pathname generated
/// by `test_resources` so that it has the correct path.
pub fn fixture_path(filename_from_test_resources: &str) -> PathBuf {
    let crate_toplevel = PathBuf::from(
        env::var_os("CARGO_MANIFEST_DIR")
            .expect(r#"CARGO_MANIFEST_DIR" is not set, please set it or run under "cargo test""#),
    );

    let workspace_toplevel = crate_toplevel.parent().unwrap();

    workspace_toplevel.join(filename_from_test_resources)
}

#[cfg(have_pangoft2)]
mod pango_ft2 {
    use super::*;
    use fontconfig_sys::fontconfig;
    use glib::prelude::*;
    use pangocairo::FontMap;

    extern "C" {
        // pango_fc_font_map_set_config (PangoFcFontMap *fcfontmap,
        //                               FcConfig       *fcconfig);
        // This is not bound in gtk-rs, and PangoFcFontMap is not even exposed, so we'll bind it by hand.
        fn pango_fc_font_map_set_config(
            font_map: *mut libc::c_void,
            config: *mut fontconfig::FcConfig,
        );
    }

    pub unsafe fn load_test_fonts() {
        let font_paths = [
            "tests/resources/Roboto-Regular.ttf",
            "tests/resources/Roboto-Italic.ttf",
            "tests/resources/Roboto-Bold.ttf",
            "tests/resources/Roboto-BoldItalic.ttf",
        ];

        let config = fontconfig::FcConfigCreate();

        for path in &font_paths {
            let path = fixture_path(path);
            let path_str = path.to_str().unwrap();
            let path_cstring = CString::new(path_str).unwrap();

            if fontconfig::FcConfigAppFontAddFile(config, path_cstring.as_ptr() as *const _) == 0 {
                panic!(
                    "Could not load font file {:?} for tests; aborting",
                    path_str
                );
            }
        }

        let font_map = FontMap::new_for_font_type(cairo::FontType::FontTypeFt).unwrap();
        let raw_font_map: *mut pango_sys::PangoFontMap = font_map.to_glib_none().0;

        pango_fc_font_map_set_config(raw_font_map as *mut _, config);
        fontconfig::FcConfigDestroy(config);

        FontMap::set_default(Some(font_map.downcast::<pangocairo::FontMap>().unwrap()));
    }
}

#[cfg(have_pangoft2)]
pub fn setup_font_map() {
    unsafe {
        self::pango_ft2::load_test_fonts();
    }
}

#[cfg(not(have_pangoft2))]
pub fn setup_font_map() {}
<|endoftext|>


<commit_before>use decoders::Image;

pub fn gamma(_: &Image, buf: &mut Vec<f32>) {
  let g: f32 = 0.45;
  let f: f32 = 0.099;
  let min: f32 = 0.018;
  let mul: f32 = 4.5;

  let maxvals = 72100; // 2^16 * 1.099 plus some margin
  let mut powlookup: Vec<f32> = vec![0.0; maxvals+1];
  for i in 0..(maxvals+1) {
    let v = (i as f32) / (maxvals as f32);
    powlookup[i] = v.powf(g);
  }

  for i in 0..buf.len() {
    let val = buf[i];

    buf[i] = if val <= min {
      mul * val
    } else {
      let part = (1.0+f) * val;
      let power = powlookup[(part.max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
      power - f
    };
  }
}
<commit_msg>gamma: do all the calculations in the lookup table<commit_after>use decoders::Image;

pub fn gamma(_: &Image, buf: &mut Vec<f32>) {
  let g: f32 = 0.45;
  let f: f32 = 0.099;
  let min: f32 = 0.018;
  let mul: f32 = 4.5;

  let maxvals = 1 << 16; // 2^16 is enough precision for any output format
  let mut glookup: Vec<f32> = vec![0.0; maxvals+1];
  for i in 0..(maxvals+1) {
    let v = (i as f32) / (maxvals as f32);
    glookup[i] = if v <= min {
      mul * v
    } else {
      ((1.0+f) * v).powf(g) - f
    }
  }

  for i in 0..buf.len() {
    let val = buf[i];

    buf[i] = glookup[(val.max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
  }
}
<|endoftext|>


<commit_before>pub mod array;
pub mod object;

pub use self::array::Array;
pub use self::object::Object;

use std::{fmt, hash};
use std::iter::FromIterator;

use unicode::UString;

#[derive(Clone, Debug)]
pub enum Value {
    Exception(UString, Object<HashableValue, Value>),
    Null,
    Boolean(bool),
    Number(i64), //TODO make this a big rational
    String(UString),
    Array(Array<Value>),
    Object(Object<HashableValue, Value>),
    Function //TODO Function(Function)
}

#[derive(Clone, Debug)]
pub enum HashableValue {
    Exception(UString, Object<HashableValue, Value>),
    Null,
    Boolean(bool),
    Number(i64), //TODO make this a big rational
    String(UString),
    Array(Array<HashableValue>),
    Object(Object<HashableValue, HashableValue>)
}

impl fmt::Display for Value {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;

        match *self {
            Exception(ref name, ref meta) => {
                try!(write!(w, "raise {:?}", name));
                if meta.len() > 0 {
                    try!(write!(w, " {{"));
                    for (i, (k, v)) in meta.iter().enumerate() {
                        if i > 0 {
                            try!(write!(w, ", "));
                        }
                        try!(k.fmt(w));
                        try!(write!(w, ": "));
                        try!(v.fmt(w));
                    }
                    try!(write!(w, "}}"));
                }
            }
            Null => {
                try!(write!(w, "null"));
            }
            Boolean(b) => {
                try!(write!(w, "{}", if b { "true" } else { "false" }));
            }
            Number(n) => {
                try!(write!(w, "{}", n));
            }
            String(ref s) => {
                try!(write!(w, "{:?}", s));
            }
            Array(ref a) => {
                try!(write!(w, "["));
                for (i, item) in a.iter().enumerate() {
                    if i > 0 {
                        try!(write!(w, ", "));
                    }
                    try!(item.fmt(w));
                }
                try!(write!(w, "]"));
            }
            Object(ref o) => {
                try!(write!(w, "{{"));
                for (i, (k, v)) in o.iter().enumerate() {
                    if i > 0 {
                        try!(write!(w, ", "));
                    }
                    try!(k.fmt(w));
                    try!(write!(w, ": "));
                    try!(v.fmt(w));
                }
                try!(write!(w, "}}"));
            }
            Function => {
                try!(write!(w, "def (...)"));
            }
        }
        Ok(())
    }
}

impl fmt::Display for HashableValue {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        Value::from(self).fmt(w)
    }
}

impl From<HashableValue> for Value {
    fn from(v: HashableValue) -> Value {
        match v {
            HashableValue::Exception(name, meta) => {
                Value::Exception(name, Object::from_iter(meta))
            }
            HashableValue::Null => {
                Value::Null
            }
            HashableValue::Boolean(b) => {
                Value::Boolean(b)
            }
            HashableValue::Number(n) => {
                Value::Number(n)
            }
            HashableValue::String(s) => {
                Value::String(s)
            }
            HashableValue::Array(a) => {
                Value::Array(Array::from_iter(a))
            }
            HashableValue::Object(o) => {
                Value::Object(Object::from_iter(o))
            }
        }
    }
}

impl<'a> From<&'a HashableValue> for Value {
    fn from(v: &HashableValue) -> Value {
        match *v {
            HashableValue::Exception(ref name, ref meta) => {
                Value::Exception(name.clone(), Object::from_iter(meta.clone()))
            }
            HashableValue::Null => {
                Value::Null
            }
            HashableValue::Boolean(b) => {
                Value::Boolean(b)
            }
            HashableValue::Number(n) => {
                Value::Number(n)
            }
            HashableValue::String(ref s) => {
                Value::String(s.clone())
            }
            HashableValue::Array(ref a) => {
                Value::Array(Array::from_iter(a.clone()))
            }
            HashableValue::Object(ref o) => {
                Value::Object(Object::from_iter(o.clone()))
            }
        }
    }
}

impl hash::Hash for HashableValue {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        use self::HashableValue::*;

        match *self {
            Exception(ref s, _) => {
                0.hash(state);
                s.hash(state);
            }
            Null => {
                1.hash(state);
            }
            Boolean(ref b) => {
                2.hash(state);
                b.hash(state);
            }
            Number(ref n) => {
                3.hash(state);
                n.hash(state);
            }
            String(ref s) => {
                4.hash(state);
                s.hash(state);
            }
            Array(ref a) => {
                5.hash(state);
                a.hash(state);
            }
            Object(ref o) => {
                6.hash(state);
                o.hash(state);
            }
        }
    }
}

impl PartialEq for HashableValue {
    fn eq(&self, other: &Self) -> bool {
        use self::HashableValue::*;

        match (self, other) {
            (&Exception(ref sl, _), &Exception(ref sr, _)) => sl == sr,
            (&Null, &Null) => true,
            (&Boolean(bl), &Boolean(br)) => bl == br,
            (&Number(nl), &Number(nr)) => nl == nr,
            (&String(ref sl), &String(ref sr)) => sl == sr,
            (&Array(ref al), &Array(ref ar)) => al == ar,
            (&Object(ref ol), &Object(ref or)) => ol == or,
            (_, _) => false
        }
    }
}

impl Eq for HashableValue {}

#[test]
fn test_values() {
    use std::collections;

    let mut array_map: collections::HashMap<Array<HashableValue>, &str> = collections::HashMap::new();
    array_map.insert(Array::from(vec![HashableValue::Boolean(false), HashableValue::Null]), "test 1");
    array_map.insert(Array::new(), "test 2");
}
<commit_msg>Fix Display for strings<commit_after>pub mod array;
pub mod object;

pub use self::array::Array;
pub use self::object::Object;

use std::{fmt, hash, string};
use std::iter::FromIterator;

use unicode::UString;

#[derive(Clone, Debug)]
pub enum Value {
    Exception(UString, Object<HashableValue, Value>),
    Null,
    Boolean(bool),
    Number(i64), //TODO make this a big rational
    String(UString),
    Array(Array<Value>),
    Object(Object<HashableValue, Value>),
    Function //TODO Function(Function)
}

#[derive(Clone, Debug)]
pub enum HashableValue {
    Exception(UString, Object<HashableValue, Value>),
    Null,
    Boolean(bool),
    Number(i64), //TODO make this a big rational
    String(UString),
    Array(Array<HashableValue>),
    Object(Object<HashableValue, HashableValue>)
}

impl fmt::Display for Value {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;

        match *self {
            Exception(ref name, ref meta) => {
                try!(write!(w, "raise {:?}", string::String::from(name)));
                if meta.len() > 0 {
                    try!(write!(w, " {{"));
                    for (i, (k, v)) in meta.iter().enumerate() {
                        if i > 0 {
                            try!(write!(w, ", "));
                        }
                        try!(k.fmt(w));
                        try!(write!(w, ": "));
                        try!(v.fmt(w));
                    }
                    try!(write!(w, "}}"));
                }
            }
            Null => {
                try!(write!(w, "null"));
            }
            Boolean(b) => {
                try!(write!(w, "{}", if b { "true" } else { "false" }));
            }
            Number(n) => {
                try!(write!(w, "{}", n));
            }
            String(ref s) => {
                try!(write!(w, "{:?}", string::String::from(s)));
            }
            Array(ref a) => {
                try!(write!(w, "["));
                for (i, item) in a.iter().enumerate() {
                    if i > 0 {
                        try!(write!(w, ", "));
                    }
                    try!(item.fmt(w));
                }
                try!(write!(w, "]"));
            }
            Object(ref o) => {
                try!(write!(w, "{{"));
                for (i, (k, v)) in o.iter().enumerate() {
                    if i > 0 {
                        try!(write!(w, ", "));
                    }
                    try!(k.fmt(w));
                    try!(write!(w, ": "));
                    try!(v.fmt(w));
                }
                try!(write!(w, "}}"));
            }
            Function => {
                try!(write!(w, "def (...)"));
            }
        }
        Ok(())
    }
}

impl fmt::Display for HashableValue {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        Value::from(self).fmt(w)
    }
}

impl From<HashableValue> for Value {
    fn from(v: HashableValue) -> Value {
        match v {
            HashableValue::Exception(name, meta) => {
                Value::Exception(name, Object::from_iter(meta))
            }
            HashableValue::Null => {
                Value::Null
            }
            HashableValue::Boolean(b) => {
                Value::Boolean(b)
            }
            HashableValue::Number(n) => {
                Value::Number(n)
            }
            HashableValue::String(s) => {
                Value::String(s)
            }
            HashableValue::Array(a) => {
                Value::Array(Array::from_iter(a))
            }
            HashableValue::Object(o) => {
                Value::Object(Object::from_iter(o))
            }
        }
    }
}

impl<'a> From<&'a HashableValue> for Value {
    fn from(v: &HashableValue) -> Value {
        match *v {
            HashableValue::Exception(ref name, ref meta) => {
                Value::Exception(name.clone(), Object::from_iter(meta.clone()))
            }
            HashableValue::Null => {
                Value::Null
            }
            HashableValue::Boolean(b) => {
                Value::Boolean(b)
            }
            HashableValue::Number(n) => {
                Value::Number(n)
            }
            HashableValue::String(ref s) => {
                Value::String(s.clone())
            }
            HashableValue::Array(ref a) => {
                Value::Array(Array::from_iter(a.clone()))
            }
            HashableValue::Object(ref o) => {
                Value::Object(Object::from_iter(o.clone()))
            }
        }
    }
}

impl hash::Hash for HashableValue {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        use self::HashableValue::*;

        match *self {
            Exception(ref s, _) => {
                0.hash(state);
                s.hash(state);
            }
            Null => {
                1.hash(state);
            }
            Boolean(ref b) => {
                2.hash(state);
                b.hash(state);
            }
            Number(ref n) => {
                3.hash(state);
                n.hash(state);
            }
            String(ref s) => {
                4.hash(state);
                s.hash(state);
            }
            Array(ref a) => {
                5.hash(state);
                a.hash(state);
            }
            Object(ref o) => {
                6.hash(state);
                o.hash(state);
            }
        }
    }
}

impl PartialEq for HashableValue {
    fn eq(&self, other: &Self) -> bool {
        use self::HashableValue::*;

        match (self, other) {
            (&Exception(ref sl, _), &Exception(ref sr, _)) => sl == sr,
            (&Null, &Null) => true,
            (&Boolean(bl), &Boolean(br)) => bl == br,
            (&Number(nl), &Number(nr)) => nl == nr,
            (&String(ref sl), &String(ref sr)) => sl == sr,
            (&Array(ref al), &Array(ref ar)) => al == ar,
            (&Object(ref ol), &Object(ref or)) => ol == or,
            (_, _) => false
        }
    }
}

impl Eq for HashableValue {}

#[test]
fn test_values() {
    use std::collections;

    let mut array_map: collections::HashMap<Array<HashableValue>, &str> = collections::HashMap::new();
    array_map.insert(Array::from(vec![HashableValue::Boolean(false), HashableValue::Null]), "test 1");
    array_map.insert(Array::new(), "test 2");
}
<|endoftext|>


<commit_before>extern mod rusp;
extern mod extra;

// for a nicer prompt, with history etc.
use extra::rl;

fn main() {
    unsafe { do rl::complete |_line, _suggest| {} }

    let mut prompt = "> ";
    let mut stored = ~"";
    println("Rusp Repl");
    let env = rusp::Rusp::new();

    loop {
        let line = match unsafe { rl::read(prompt) } {
            Some(line) => line,
            None => break
        };

        if !stored.is_empty() { stored.push_char('\n'); }
        stored.push_str(line);
        unsafe { rl::add_history(line); }

        let continue_line = match rusp::parse(stored) {
            Ok(ex) => {
                // print the AST, since that's useful for debugging
                println(fmt!("AST: %?" ex));
                // separate, since this can make the REPL crash
                println(match env.eval(&ex) {
                    Ok(evaled) => evaled.to_str(),
                    Err(e) => {
                        fmt!("Error: %s", e)
                    }
                });
                false
            }
            Err(ref er) if er.description == ~"Unexpected EOF" => {
                // it's not invalid yet, just haven't got enough
                // input, so wait for more
                true
            }
            Err(ref er) => {
                // give a little caret pointing at the serror
                println(fmt!("%s^\nParse Error: %s",
                             str::repeat(" ", er.position.col - 1 + prompt.len()),
                             er.description));
                false
            }
        };

        prompt = if continue_line {
            "+ "
        } else {
            stored = ~"";
            "> "
        }
    }
}
<commit_msg>Usability improvements to the repl, don't print () or the AST.<commit_after>extern mod rusp;
extern mod extra;

// for a nicer prompt, with history etc.
use extra::rl;

fn main() {
    unsafe { do rl::complete |_line, _suggest| {} }

    let mut prompt = "> ";
    let mut stored = ~"";
    println("Rusp Repl");
    let env = rusp::Rusp::new();

    loop {
        let line = match unsafe { rl::read(prompt) } {
            Some(line) => line,
            None => break
        };

        if !stored.is_empty() { stored.push_char('\n'); }
        else if line.is_empty() {
            // no input and no history
            loop;
        }
        stored.push_str(line);

        if !line.is_empty() {
            unsafe { rl::add_history(line); }
        }

        let continue_line = match rusp::parse(stored) {
            Ok(ex) => {
                let to_print = match env.eval(&ex) {
                    Ok(evaled) => evaled.to_str(),
                    Err(e) => {
                        fmt!("Error: %s", e)
                    }
                };

                if to_print != ~"()" {
                    println(to_print);
                }
                false
            }
            Err(ref er) if er.description == ~"Unexpected EOF" => {
                // it's not invalid yet, just haven't got enough
                // input, so wait for more
                true
            }
            Err(ref er) => {
                // give a little caret pointing at the serror
                println(fmt!("%s^\nParse Error: %s",
                             str::repeat(" ", er.position.col - 1 + prompt.len()),
                             er.description));
                false
            }
        };

        prompt = if continue_line {
            "+ "
        } else {
            stored = ~"";
            "> "
        }
    }
}
<|endoftext|>


<commit_before>use bindings::{
    jit_context_t,
    jit_context_create,
    jit_context_destroy,
    jit_context_build_start,
    jit_context_build_end,
    jit_function_t,
    jit_function_next
};
use function::Function;
use std::kinds::marker::ContravariantLifetime;
use util::NativeRef;
/// Holds all of the functions you have built and compiled. There can be
/// multiple, but normally there is only one.
native_ref!(Context, _context, jit_context_t, ContravariantLifetime)
impl<'a> Context<'a> {
    #[inline(always)]
    /// Create a new JIT Context
    pub fn new() -> Context<'a> {
        unsafe {
            NativeRef::from_ptr(jit_context_create())
        }
    }
    /// Run a closure that can generate IR
    pub fn build<R>(&self, cb: || -> R) -> R {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let rv = cb();
            jit_context_build_end(self.as_ptr());
            rv
        }
    }
    /// Iterate through all the functions in this context
    #[inline]
    pub fn iter_funcs(&self) -> Functions<'a> {
        Functions::new(self)
    }
}
#[unsafe_destructor]
impl<'a> Drop for Context<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_context_destroy(self.as_ptr());
        }
    }
}
/// Any JIT object which is in a context
pub trait InContext<'a> {
    /// Get the context for this object
    fn get_context(&self) -> Context<'a>;
}

/// An iterator over a context's functions
pub struct Functions<'a> {
    ctx: jit_context_t,
    last: jit_function_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> Functions<'a> {
    fn new(ctx:&Context<'a>) -> Functions<'a> {
        unsafe {
            Functions {
                ctx: ctx.as_ptr(),
                last: RawPtr::null(),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Function<'a>> for Functions<'a> {
    fn next(&mut self) -> Option<Function> {
        unsafe {
            let native_next = jit_function_next(self.ctx, self.last);
            self.last = native_next;
            NativeRef::from_ptr(native_next)
        }
    }
    fn size_hint(&self) -> (uint, Option<uint>) {
        let mut size : uint = 0;
        let mut last = self.last;
        loop {
            last = unsafe {
                jit_function_next(self.ctx, last)
            };
            if last.is_null() {
                break;
            } else {
                size += 1;
            }
        }
        (size, Some(size))
    }
}<commit_msg>Rename context function iterator to `funcs`<commit_after>use bindings::{
    jit_context_t,
    jit_context_create,
    jit_context_destroy,
    jit_context_build_start,
    jit_context_build_end,
    jit_function_t,
    jit_function_next
};
use function::Function;
use std::kinds::marker::ContravariantLifetime;
use util::NativeRef;
/// Holds all of the functions you have built and compiled. There can be
/// multiple, but normally there is only one.
native_ref!(Context, _context, jit_context_t, ContravariantLifetime)
impl<'a> Context<'a> {
    #[inline(always)]
    /// Create a new JIT Context
    pub fn new() -> Context<'a> {
        unsafe {
            NativeRef::from_ptr(jit_context_create())
        }
    }
    /// Run a closure that can generate IR
    pub fn build<R>(&self, cb: || -> R) -> R {
        unsafe {
            jit_context_build_start(self.as_ptr());
            let rv = cb();
            jit_context_build_end(self.as_ptr());
            rv
        }
    }
    /// Iterate through all the functions in this context
    #[inline(always)]
    pub fn funcs(&self) -> Functions<'a> {
        Functions::new(self)
    }
}
#[unsafe_destructor]
impl<'a> Drop for Context<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_context_destroy(self.as_ptr());
        }
    }
}
/// Any JIT object which is in a context
pub trait InContext<'a> {
    /// Get the context for this object
    fn get_context(&self) -> Context<'a>;
}

/// An iterator over a context's functions
pub struct Functions<'a> {
    ctx: jit_context_t,
    last: jit_function_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> Functions<'a> {
    fn new(ctx:&Context<'a>) -> Functions<'a> {
        unsafe {
            Functions {
                ctx: ctx.as_ptr(),
                last: RawPtr::null(),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Function<'a>> for Functions<'a> {
    fn next(&mut self) -> Option<Function> {
        unsafe {
            let native_next = jit_function_next(self.ctx, self.last);
            self.last = native_next;
            NativeRef::from_ptr(native_next)
        }
    }
    fn size_hint(&self) -> (uint, Option<uint>) {
        let mut size : uint = 0;
        let mut last = self.last;
        loop {
            last = unsafe {
                jit_function_next(self.ctx, last)
            };
            if last.is_null() {
                break;
            } else {
                size += 1;
            }
        }
        (size, Some(size))
    }
}<|endoftext|>