<commit_before>//! The type system. We currently use this to infer types for completion, hover
//! information and various assists.

#![allow(unused)]

#[allow(unused)]
macro_rules! eprintln {
    ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
}

mod autoderef;
pub mod primitive;
pub mod traits;
pub mod method_resolution;
mod op;
mod lower;
pub(crate) mod infer;
pub(crate) mod utils;
mod chalk_cast;
mod chalk_ext;
mod builder;
mod walk;

pub mod display;
pub mod db;
pub mod diagnostics;

#[cfg(test)]
mod tests;
#[cfg(test)]
mod test_db;

use std::sync::Arc;

use base_db::salsa;
use chalk_ir::{
    cast::{CastTo, Caster},
    interner::HasInterner,
    UintTy,
};
use hir_def::{
    expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId,
    TypeParamId,
};

use crate::{db::HirDatabase, display::HirDisplay, utils::generics};

pub use autoderef::autoderef;
pub use builder::TyBuilder;
pub use chalk_ext::*;
pub use infer::{could_unify, InferenceResult};
pub use lower::{
    associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
    TyDefId, TyLoweringContext, ValueTyDefId,
};
pub use traits::{chalk::Interner, TraitEnvironment};
pub use walk::TypeWalk;

pub use chalk_ir::{
    cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
};

pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
pub type FnDefId = chalk_ir::FnDefId<Interner>;
pub type ClosureId = chalk_ir::ClosureId<Interner>;
pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;

pub type VariableKind = chalk_ir::VariableKind<Interner>;
pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
pub type Binders<T> = chalk_ir::Binders<T>;
pub type Substitution = chalk_ir::Substitution<Interner>;
pub type GenericArg = chalk_ir::GenericArg<Interner>;
pub type GenericArgData = chalk_ir::GenericArgData<Interner>;

pub type Ty = chalk_ir::Ty<Interner>;
pub type TyKind = chalk_ir::TyKind<Interner>;
pub type DynTy = chalk_ir::DynTy<Interner>;
pub type FnPointer = chalk_ir::FnPointer<Interner>;
// pub type FnSubst = chalk_ir::FnSubst<Interner>;
pub use chalk_ir::FnSubst;
pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
pub type AliasTy = chalk_ir::AliasTy<Interner>;
pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
pub type InferenceVar = chalk_ir::InferenceVar;

pub type Lifetime = chalk_ir::Lifetime<Interner>;
pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;

pub type Const = chalk_ir::Const<Interner>;
pub type ConstData = chalk_ir::ConstData<Interner>;
pub type ConstValue = chalk_ir::ConstValue<Interner>;
pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;

pub type ChalkTraitId = chalk_ir::TraitId<Interner>;

pub type FnSig = chalk_ir::FnSig<Interner>;

pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
pub type AliasEq = chalk_ir::AliasEq<Interner>;
pub type Solution = chalk_solve::Solution<Interner>;
pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
pub type Guidance = chalk_solve::Guidance<Interner>;
pub type WhereClause = chalk_ir::WhereClause<Interner>;

// FIXME: get rid of this
pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
    Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into())
}

/// Return an index of a parameter in the generic type parameter list by it's id.
pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
    generics(db.upcast(), id.parent).param_idx(id)
}

pub fn wrap_empty_binders<T>(value: T) -> Binders<T>
where
    T: TypeWalk + HasInterner<Interner = Interner>,
{
    Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
}

pub fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
    num_vars: usize,
    value: T,
) -> Binders<T> {
    Binders::new(
        VariableKinds::from_iter(
            &Interner,
            std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
                .take(num_vars),
        ),
        value,
    )
}

// FIXME: get rid of this
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
    value: T,
    kinds: impl IntoIterator<Item = TyVariableKind>,
) -> Canonical<T> {
    let kinds = kinds.into_iter().map(|tk| {
        chalk_ir::CanonicalVarKind::new(
            chalk_ir::VariableKind::Ty(tk),
            chalk_ir::UniverseIndex::ROOT,
        )
    });
    Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
}

pub type TraitRef = chalk_ir::TraitRef<Interner>;

pub type QuantifiedWhereClause = Binders<WhereClause>;

pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;

pub type Canonical<T> = chalk_ir::Canonical<T>;

/// A function signature as seen by type inference: Several parameter types and
/// one return type.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CallableSig {
    params_and_return: Arc<[Ty]>,
    is_varargs: bool,
}

/// A polymorphic function signature.
pub type PolyFnSig = Binders<CallableSig>;

impl CallableSig {
    pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
        params.push(ret);
        CallableSig { params_and_return: params.into(), is_varargs }
    }

    pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
        CallableSig {
            // FIXME: what to do about lifetime params? -> return PolyFnSig
            params_and_return: fn_ptr
                .substitution
                .clone()
                .shifted_out_to(DebruijnIndex::ONE)
                .expect("unexpected lifetime vars in fn ptr")
                .0
                .interned()
                .iter()
                .map(|arg| arg.assert_ty_ref(&Interner).clone())
                .collect(),
            is_varargs: fn_ptr.sig.variadic,
        }
    }

    pub fn params(&self) -> &[Ty] {
        &self.params_and_return[0..self.params_and_return.len() - 1]
    }

    pub fn ret(&self) -> &Ty {
        &self.params_and_return[self.params_and_return.len() - 1]
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum ImplTraitId {
    ReturnTypeImplTrait(hir_def::FunctionId, u16),
    AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct ReturnTypeImplTraits {
    pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct ReturnTypeImplTrait {
    pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
}

pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
    chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
    chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_type_param_id(interned_id)
}

pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex {
    let interned_id = db.intern_type_param_id(id);
    PlaceholderIndex {
        ui: chalk_ir::UniverseIndex::ROOT,
        idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
    }
}

pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_lifetime_param_id(interned_id)
}

pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_const_param_id(interned_id)
}

pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
    chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn static_lifetime() -> Lifetime {
    LifetimeData::Static.intern(&Interner)
}

pub fn dummy_usize_const() -> Const {
    let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
    chalk_ir::ConstData {
        ty: usize_ty,
        value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
    }
    .intern(&Interner)
}
<commit_msg>Impl Fold for CallableSig<commit_after>//! The type system. We currently use this to infer types for completion, hover
//! information and various assists.

#![allow(unused)]

#[allow(unused)]
macro_rules! eprintln {
    ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
}

mod autoderef;
pub mod primitive;
pub mod traits;
pub mod method_resolution;
mod op;
mod lower;
pub(crate) mod infer;
pub(crate) mod utils;
mod chalk_cast;
mod chalk_ext;
mod builder;
mod walk;

pub mod display;
pub mod db;
pub mod diagnostics;

#[cfg(test)]
mod tests;
#[cfg(test)]
mod test_db;

use std::sync::Arc;

use base_db::salsa;
use chalk_ir::{
    cast::{CastTo, Caster},
    fold::Fold,
    interner::HasInterner,
    UintTy,
};
use hir_def::{
    expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId,
    TypeParamId,
};

use crate::{db::HirDatabase, display::HirDisplay, utils::generics};

pub use autoderef::autoderef;
pub use builder::TyBuilder;
pub use chalk_ext::*;
pub use infer::{could_unify, InferenceResult};
pub use lower::{
    associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
    TyDefId, TyLoweringContext, ValueTyDefId,
};
pub use traits::{chalk::Interner, TraitEnvironment};
pub use walk::TypeWalk;

pub use chalk_ir::{
    cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
};

pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
pub type FnDefId = chalk_ir::FnDefId<Interner>;
pub type ClosureId = chalk_ir::ClosureId<Interner>;
pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;

pub type VariableKind = chalk_ir::VariableKind<Interner>;
pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
pub type Binders<T> = chalk_ir::Binders<T>;
pub type Substitution = chalk_ir::Substitution<Interner>;
pub type GenericArg = chalk_ir::GenericArg<Interner>;
pub type GenericArgData = chalk_ir::GenericArgData<Interner>;

pub type Ty = chalk_ir::Ty<Interner>;
pub type TyKind = chalk_ir::TyKind<Interner>;
pub type DynTy = chalk_ir::DynTy<Interner>;
pub type FnPointer = chalk_ir::FnPointer<Interner>;
// pub type FnSubst = chalk_ir::FnSubst<Interner>;
pub use chalk_ir::FnSubst;
pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
pub type AliasTy = chalk_ir::AliasTy<Interner>;
pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
pub type InferenceVar = chalk_ir::InferenceVar;

pub type Lifetime = chalk_ir::Lifetime<Interner>;
pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;

pub type Const = chalk_ir::Const<Interner>;
pub type ConstData = chalk_ir::ConstData<Interner>;
pub type ConstValue = chalk_ir::ConstValue<Interner>;
pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;

pub type ChalkTraitId = chalk_ir::TraitId<Interner>;

pub type FnSig = chalk_ir::FnSig<Interner>;

pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
pub type AliasEq = chalk_ir::AliasEq<Interner>;
pub type Solution = chalk_solve::Solution<Interner>;
pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
pub type Guidance = chalk_solve::Guidance<Interner>;
pub type WhereClause = chalk_ir::WhereClause<Interner>;

// FIXME: get rid of this
pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
    Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into())
}

/// Return an index of a parameter in the generic type parameter list by it's id.
pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
    generics(db.upcast(), id.parent).param_idx(id)
}

pub fn wrap_empty_binders<T>(value: T) -> Binders<T>
where
    T: TypeWalk + HasInterner<Interner = Interner>,
{
    Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
}

pub fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
    num_vars: usize,
    value: T,
) -> Binders<T> {
    Binders::new(
        VariableKinds::from_iter(
            &Interner,
            std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
                .take(num_vars),
        ),
        value,
    )
}

// FIXME: get rid of this
pub fn make_canonical<T: HasInterner<Interner = Interner>>(
    value: T,
    kinds: impl IntoIterator<Item = TyVariableKind>,
) -> Canonical<T> {
    let kinds = kinds.into_iter().map(|tk| {
        chalk_ir::CanonicalVarKind::new(
            chalk_ir::VariableKind::Ty(tk),
            chalk_ir::UniverseIndex::ROOT,
        )
    });
    Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
}

pub type TraitRef = chalk_ir::TraitRef<Interner>;

pub type QuantifiedWhereClause = Binders<WhereClause>;

pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;

pub type Canonical<T> = chalk_ir::Canonical<T>;

/// A function signature as seen by type inference: Several parameter types and
/// one return type.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct CallableSig {
    params_and_return: Arc<[Ty]>,
    is_varargs: bool,
}

/// A polymorphic function signature.
pub type PolyFnSig = Binders<CallableSig>;

impl CallableSig {
    pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
        params.push(ret);
        CallableSig { params_and_return: params.into(), is_varargs }
    }

    pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
        CallableSig {
            // FIXME: what to do about lifetime params? -> return PolyFnSig
            params_and_return: fn_ptr
                .substitution
                .clone()
                .shifted_out_to(DebruijnIndex::ONE)
                .expect("unexpected lifetime vars in fn ptr")
                .0
                .interned()
                .iter()
                .map(|arg| arg.assert_ty_ref(&Interner).clone())
                .collect(),
            is_varargs: fn_ptr.sig.variadic,
        }
    }

    pub fn params(&self) -> &[Ty] {
        &self.params_and_return[0..self.params_and_return.len() - 1]
    }

    pub fn ret(&self) -> &Ty {
        &self.params_and_return[self.params_and_return.len() - 1]
    }
}

impl Fold<Interner> for CallableSig {
    type Result = CallableSig;

    fn fold_with<'i>(
        self,
        folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
        outer_binder: DebruijnIndex,
    ) -> chalk_ir::Fallible<Self::Result>
    where
        Interner: 'i,
    {
        let vec = self.params_and_return.to_vec();
        let folded = vec.fold_with(folder, outer_binder)?;
        Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum ImplTraitId {
    ReturnTypeImplTrait(hir_def::FunctionId, u16),
    AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct ReturnTypeImplTraits {
    pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct ReturnTypeImplTrait {
    pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
}

pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
    chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
    chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_type_param_id(interned_id)
}

pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex {
    let interned_id = db.intern_type_param_id(id);
    PlaceholderIndex {
        ui: chalk_ir::UniverseIndex::ROOT,
        idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
    }
}

pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_lifetime_param_id(interned_id)
}

pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
    assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
    let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
    db.lookup_intern_const_param_id(interned_id)
}

pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
    chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
}

pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
    salsa::InternKey::from_intern_id(id.0)
}

pub fn static_lifetime() -> Lifetime {
    LifetimeData::Static.intern(&Interner)
}

pub fn dummy_usize_const() -> Const {
    let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
    chalk_ir::ConstData {
        ty: usize_ty,
        value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
    }
    .intern(&Interner)
}
<|endoftext|>


<commit_before>use cgmath::Vector2;
use time::Duration;
use input_state::{InputState, GameButton};
use warp_horizon::UpdateDelta;

/// A type containing the data to convert between world and screen positions.
/// Also includes functionality for moving the camera around based on player input.
pub struct Camera {
    resolution: Vector2<i32>,
    position: Vector2<f32>,
    zoom: i32,
    move_speed: f32,
}

impl Camera {
    pub fn new(resolution: Vector2<i32>) -> Self {
        Camera {
            resolution: resolution,
            position: Vector2::new(0.0, 0.0),
            zoom: 1,
            move_speed: 1.0,
        }
    }

    pub fn position(&self) -> Vector2<f32> {
        self.position
    }

    pub fn set_position(&mut self, value: Vector2<f32>) {
        self.position = value;
    }

    pub fn zoom(&self) -> i32 {
        self.zoom
    }

    pub fn set_zoom(&mut self, value: i32) {
        self.zoom = value;
    }

    pub fn set_move_speed(&mut self, value: f32) {
        self.move_speed = value;
    }

    fn screen_to_renderplane(&self, value: Vector2<i32>) -> Vector2<f32> {
        // Get the distance from the center of the screen in screen coordinates
        let from_center: Vector2<f32> = (value - (self.resolution/2)).cast();

        // Calculate the distance from the center of the screen in renderplane coordinates and
        // add those to the position of the center
        self.position + (from_center / (self.zoom as f32))
    }

    fn renderplane_to_world(&self, value: Vector2<f32>) -> Vector2<f32> {
        // Misc trivial data before the actual calculation
        let tile = Vector2::new(32.0, 15.0);

        // The actual calculation just adds a certain amount to world-x and world-y per each
        // screen-x and screen-y, there's some room for optimization here if it becomes a problem
        // The +1 is needed on the y because there's 1 pixel of extra distance so the tiles
        // can slot together better
        let offset_from_x = Vector2::new(1.0, -1.0) * (value.x / tile.x);
        let offset_from_y = Vector2::new(1.0, 1.0) * (value.y / (tile.y+1.0));

        offset_from_x + offset_from_y
    }

    /// Calculates the equivalent coordinates in world for coordinates on screen.
    pub fn screen_to_world(&self, value: Vector2<i32>) -> Vector2<f32> {
        self.renderplane_to_world(self.screen_to_renderplane(value))
    }

    pub fn update(&mut self, state: &InputState, delta: Duration) {
        let mut direction = Vector2::new(0.0, 0.0);

        if state.key(GameButton::MoveCameraRight) { direction.x += 1.0; }
        if state.key(GameButton::MoveCameraLeft) { direction.x -= 1.0; }
        if state.key(GameButton::MoveCameraUp) { direction.y += 1.0; }
        if state.key(GameButton::MoveCameraDown) { direction.y -= 1.0; }

        self.position = self.position + (delta.scale(direction) * self.move_speed);
    }
}

#[cfg(test)]
mod tests {
    use cgmath::Vector2;
    use time::Duration;
    use camera::Camera;
    use input_state::{InputState, GameButton};

    #[test]
    fn update_with_arrow_key_input_moves_camera() {
        let mut camera = Camera::new(Vector2::new(100, 50));
        assert!(camera.position().x == 0.0);
        assert!(camera.position().y == 0.0);

        let mut input_state = InputState::new();
        input_state.set_key(GameButton::MoveCameraRight, true);
        input_state.set_key(GameButton::MoveCameraUp, true);

        camera.update(&input_state, Duration::milliseconds(20));

        assert!(camera.position().x > 0.0);
        assert!(camera.position().y > 0.0);
    }

    #[test]
    fn update_with_different_speeds_moves_at_different_rates() {
        let mut slow_cam = Camera::new(Vector2::new(100, 50));
        slow_cam.set_move_speed(1.0);
        let mut fast_cam = Camera::new(Vector2::new(100, 50));
        fast_cam.set_move_speed(2.0);

        let mut input_state = InputState::new();
        input_state.set_key(GameButton::MoveCameraRight, true);

        slow_cam.update(&input_state, Duration::milliseconds(20));
        fast_cam.update(&input_state, Duration::milliseconds(20));

        assert!(slow_cam.position().x < fast_cam.position().x);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_at_origin_with_no_zoom() {
        let cam = Camera::new(Vector2::new(100, 50));

        // Origin
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 0.0);
        assert_eq!(world1.y.floor(), 0.0);

        // Difference in the Y direction
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + 16));
        assert_eq!(world2.x.floor(), 1.0);
        assert_eq!(world2.y.floor(), 1.0);

        // Difference in the X direction
        let world3 = cam.screen_to_world(Vector2::new(50 + 16, 26));
        assert_eq!(world3.x.floor(), 0.0);
        assert_eq!(world3.y.floor(), -1.0);

        // More complex position
        let world3 = cam.screen_to_world(Vector2::new(50 + 16, 26 + (16*20)));
        assert_eq!(world3.x.floor(), 20.0);
        assert_eq!(world3.y.floor(), 19.0);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_with_zooming() {
        let mut cam = Camera::new(Vector2::new(100, 50));
        cam.set_zoom(4);

        // Origin
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 0.0);
        assert_eq!(world1.y.floor(), 0.0);

        // Origin + 1 tile size down
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + (16*4)));
        assert_eq!(world2.x.floor(), 1.0);
        assert_eq!(world2.y.floor(), 1.0);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_with_position() {
        let mut cam = Camera::new(Vector2::new(100, 50));
        cam.set_position(Vector2::new(-16.0, 30.0));

        // Middle of screen
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 1.0);
        assert_eq!(world1.y.floor(), 2.0);

        // Middle of screen + 1 tile size down
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + 15));
        assert_eq!(world2.x.floor(), 2.0);
        assert_eq!(world2.y.floor(), 3.0);
    }
}
<commit_msg>Fix position of camera being interpreted upside down<commit_after>use cgmath::Vector2;
use time::Duration;
use input_state::{InputState, GameButton};
use warp_horizon::UpdateDelta;

/// A type containing the data to convert between world and screen positions.
/// Also includes functionality for moving the camera around based on player input.
pub struct Camera {
    resolution: Vector2<i32>,
    position: Vector2<f32>,
    zoom: i32,
    move_speed: f32,
}

impl Camera {
    pub fn new(resolution: Vector2<i32>) -> Self {
        Camera {
            resolution: resolution,
            position: Vector2::new(0.0, 0.0),
            zoom: 1,
            move_speed: 1.0,
        }
    }

    pub fn position(&self) -> Vector2<f32> {
        self.position
    }

    pub fn set_position(&mut self, value: Vector2<f32>) {
        self.position = value;
    }

    pub fn zoom(&self) -> i32 {
        self.zoom
    }

    pub fn set_zoom(&mut self, value: i32) {
        self.zoom = value;
    }

    pub fn set_move_speed(&mut self, value: f32) {
        self.move_speed = value;
    }

    fn screen_to_renderplane(&self, value: Vector2<i32>) -> Vector2<f32> {
        // Get the distance from the center of the screen in screen coordinates
        let mut from_center: Vector2<f32> = (value - (self.resolution/2)).cast();

        // Screen coordinates are top-bottom y, renderplane coordinates are bottom-top y
        from_center.y = -from_center.y;

        // Calculate the distance from the center of the screen in renderplane coordinates and
        // add those to the position of the center
        self.position + (from_center / (self.zoom as f32))
    }

    fn renderplane_to_world(&self, value: Vector2<f32>) -> Vector2<f32> {
        // Misc trivial data before the actual calculation
        let tile = Vector2::new(32.0, 15.0);

        // The actual calculation just adds a certain amount to world-x and world-y per each
        // screen-x and screen-y, there's some room for optimization here if it becomes a problem
        // The +1 is needed on the y because there's 1 pixel of extra distance so the tiles
        // can slot together better
        let offset_from_x = Vector2::new(1.0, -1.0) * (value.x / tile.x);
        let offset_from_y = Vector2::new(-1.0, -1.0) * (value.y / (tile.y+1.0));

        offset_from_x + offset_from_y
    }

    /// Calculates the equivalent coordinates in world for coordinates on screen.
    pub fn screen_to_world(&self, value: Vector2<i32>) -> Vector2<f32> {
        self.renderplane_to_world(self.screen_to_renderplane(value))
    }

    pub fn update(&mut self, state: &InputState, delta: Duration) {
        let mut direction = Vector2::new(0.0, 0.0);

        if state.key(GameButton::MoveCameraRight) { direction.x += 1.0; }
        if state.key(GameButton::MoveCameraLeft) { direction.x -= 1.0; }
        if state.key(GameButton::MoveCameraUp) { direction.y += 1.0; }
        if state.key(GameButton::MoveCameraDown) { direction.y -= 1.0; }

        self.position = self.position + (delta.scale(direction) * self.move_speed);
    }
}

#[cfg(test)]
mod tests {
    use cgmath::Vector2;
    use time::Duration;
    use camera::Camera;
    use input_state::{InputState, GameButton};

    #[test]
    fn update_with_arrow_key_input_moves_camera() {
        let mut camera = Camera::new(Vector2::new(100, 50));
        assert!(camera.position().x == 0.0);
        assert!(camera.position().y == 0.0);

        let mut input_state = InputState::new();
        input_state.set_key(GameButton::MoveCameraRight, true);
        input_state.set_key(GameButton::MoveCameraUp, true);

        camera.update(&input_state, Duration::milliseconds(20));

        assert!(camera.position().x > 0.0);
        assert!(camera.position().y > 0.0);
    }

    #[test]
    fn update_with_different_speeds_moves_at_different_rates() {
        let mut slow_cam = Camera::new(Vector2::new(100, 50));
        slow_cam.set_move_speed(1.0);
        let mut fast_cam = Camera::new(Vector2::new(100, 50));
        fast_cam.set_move_speed(2.0);

        let mut input_state = InputState::new();
        input_state.set_key(GameButton::MoveCameraRight, true);

        slow_cam.update(&input_state, Duration::milliseconds(20));
        fast_cam.update(&input_state, Duration::milliseconds(20));

        assert!(slow_cam.position().x < fast_cam.position().x);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_at_origin_with_no_zoom() {
        let cam = Camera::new(Vector2::new(100, 50));

        // Origin
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 0.0);
        assert_eq!(world1.y.floor(), 0.0);

        // Difference in the Y direction
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + 16));
        assert_eq!(world2.x.floor(), 1.0);
        assert_eq!(world2.y.floor(), 1.0);

        // Difference in the X direction
        let world3 = cam.screen_to_world(Vector2::new(50 + 16, 26));
        assert_eq!(world3.x.floor(), 0.0);
        assert_eq!(world3.y.floor(), -1.0);

        // More complex position
        let world3 = cam.screen_to_world(Vector2::new(50 + 16, 26 + (16*20)));
        assert_eq!(world3.x.floor(), 20.0);
        assert_eq!(world3.y.floor(), 19.0);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_with_zooming() {
        let mut cam = Camera::new(Vector2::new(100, 50));
        cam.set_zoom(4);

        // Origin
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 0.0);
        assert_eq!(world1.y.floor(), 0.0);

        // Origin + 1 tile size down
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + (16*4)));
        assert_eq!(world2.x.floor(), 1.0);
        assert_eq!(world2.y.floor(), 1.0);
    }

    #[test]
    fn screen_to_world_returns_correct_tile_with_position() {
        let mut cam = Camera::new(Vector2::new(100, 50));
        cam.set_position(Vector2::new(-16.0, -30.0));

        // Middle of screen
        let world1 = cam.screen_to_world(Vector2::new(50, 26));
        assert_eq!(world1.x.floor(), 1.0);
        assert_eq!(world1.y.floor(), 2.0);

        // Middle of screen + 1 tile size down
        let world2 = cam.screen_to_world(Vector2::new(50, 26 + 15));
        assert_eq!(world2.x.floor(), 2.0);
        assert_eq!(world2.y.floor(), 3.0);
    }
}
<|endoftext|>


<commit_before>//! This crate contains a single public function
//! [`get_path_for_executable`](fn.get_path_for_executable.html).
//! See docs there for more information.

use anyhow::{Error, Result};
use std::env;
use std::path::Path;
use std::process::Command;

/// Return a `String` to use for the given executable.
///
/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
/// gives a valid Cargo executable; or it may return a full path to a valid
/// Cargo.
pub fn get_path_for_executable(executable_name: impl AsRef<str>) -> Result<String> {
    // The current implementation checks three places for an executable to use:
    // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
    //      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
    // 2) `<executable_name>`
    //      example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
    // 3) `~/.cargo/bin/<executable_name>`
    //      example: for cargo, this tries ~/.cargo/bin/cargo
    //      It seems that this is a reasonable place to try for cargo, rustc, and rustup
    let executable_name = executable_name.as_ref();
    let env_var = executable_name.to_ascii_uppercase();
    if let Ok(path) = env::var(&env_var) {
        if is_valid_executable(&path) {
            Ok(path)
        } else {
            Err(Error::msg(format!(
                "`{}` environment variable points to something that's not a valid executable",
                env_var
            )))
        }
    } else {
        let final_path: Option<String> = if is_valid_executable(executable_name) {
            Some(executable_name.to_owned())
        } else {
            if let Some(mut path) = dirs::home_dir() {
                path.push(".cargo");
                path.push("bin");
                path.push(executable_name);
                if is_valid_executable(&path) {
                    Some(path.into_os_string().into_string().expect("Invalid Unicode in path"))
                } else {
                    None
                }
            } else {
                None
            }
        };
        final_path.ok_or(
            // This error message may also be caused by $PATH or $CARGO/$RUSTC/etc not being set correctly
            // for VSCode, even if they are set correctly in a terminal.
            // On macOS in particular, launching VSCode from terminal with `code <dirname>` causes VSCode
            // to inherit environment variables including $PATH, $CARGO, $RUSTC, etc from that terminal;
            // but launching VSCode from Dock does not inherit environment variables from a terminal.
            // For more discussion, see #3118.
            Error::msg(format!("Failed to find `{}` executable. Make sure `{}` is in `$PATH`, or set `${}` to point to a valid executable.", executable_name, executable_name, env_var))
        )
    }
}

/// Does the given `Path` point to a usable executable?
///
/// (assumes the executable takes a `--version` switch and writes to stdout,
/// which is true for `cargo`, `rustc`, and `rustup`)
fn is_valid_executable(p: impl AsRef<Path>) -> bool {
    Command::new(p.as_ref()).arg("--version").output().is_ok()
}
<commit_msg>simplify some code using early returns<commit_after>//! This crate contains a single public function
//! [`get_path_for_executable`](fn.get_path_for_executable.html).
//! See docs there for more information.

use anyhow::{Error, Result};
use std::env;
use std::path::Path;
use std::process::Command;

/// Return a `String` to use for the given executable.
///
/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
/// gives a valid Cargo executable; or it may return a full path to a valid
/// Cargo.
pub fn get_path_for_executable(executable_name: impl AsRef<str>) -> Result<String> {
    // The current implementation checks three places for an executable to use:
    // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
    //      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
    // 2) `<executable_name>`
    //      example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
    // 3) `~/.cargo/bin/<executable_name>`
    //      example: for cargo, this tries ~/.cargo/bin/cargo
    //      It seems that this is a reasonable place to try for cargo, rustc, and rustup
    let executable_name = executable_name.as_ref();
    let env_var = executable_name.to_ascii_uppercase();
    if let Ok(path) = env::var(&env_var) {
        if is_valid_executable(&path) {
            Ok(path)
        } else {
            Err(Error::msg(format!(
                "`{}` environment variable points to something that's not a valid executable",
                env_var
            )))
        }
    } else {
        if is_valid_executable(executable_name) {
            return Ok(executable_name.to_owned());
        }
        if let Some(mut path) = dirs::home_dir() {
            path.push(".cargo");
            path.push("bin");
            path.push(executable_name);
            if is_valid_executable(&path) {
                return Ok(path.into_os_string().into_string().expect("Invalid Unicode in path"));
            }
        }
        // This error message may also be caused by $PATH or $CARGO/$RUSTC/etc not being set correctly
        // for VSCode, even if they are set correctly in a terminal.
        // On macOS in particular, launching VSCode from terminal with `code <dirname>` causes VSCode
        // to inherit environment variables including $PATH, $CARGO, $RUSTC, etc from that terminal;
        // but launching VSCode from Dock does not inherit environment variables from a terminal.
        // For more discussion, see #3118.
        Err(Error::msg(format!("Failed to find `{}` executable. Make sure `{}` is in `$PATH`, or set `${}` to point to a valid executable.", executable_name, executable_name, env_var)))
    }
}

/// Does the given `Path` point to a usable executable?
///
/// (assumes the executable takes a `--version` switch and writes to stdout,
/// which is true for `cargo`, `rustc`, and `rustup`)
fn is_valid_executable(p: impl AsRef<Path>) -> bool {
    Command::new(p.as_ref()).arg("--version").output().is_ok()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Matthew O'Connor

//! Abstract syntax tree for System Zero Core
//!
//! Defines AST and traits for debugging and normalizing expressions.

use std::fmt::{Debug, Formatter, Error};

/// `Const` defines the builtin types of types.
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Const {
  /// `Data` is finite and all functions on it must be total.
  Data,
  /// `Codata` is potentially infinite and corecursion must be productive.
  Codata,
}

/// `Var` is the label for a bound variable.
#[derive(Clone, Eq, PartialEq)]
pub struct Var {
  /// `name` is the label.
  name: String,
  /// `idx` is the De Bruijn index, in theory.
  idx: i32,
}

/// `Expr` represents all computations in System Zero Core.
#[derive(Clone, Eq, PartialEq)]
pub enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

/// `Def`s are bindings between `Var` and values or types.
#[derive(Clone, Eq, PartialEq)]
pub enum Def {
  Val(Var, Expr),
  Ty(Var, Expr),
}

/// `One` represents one top-level element. It needs a better name.
#[derive(Clone, Eq, PartialEq)]
pub enum One {
  Def(Def),
  Expr(Expr),
}

/// `Mod` is all of the code for a given module.
#[derive(Clone, Eq, PartialEq)]
pub struct Mod {
  listing: Vec<One>,
}

// # Traits

/// `Normalize` converts the value to a strongly normalized version.
/// Normalization in a total typed lambda calculus is essentially inlining
/// until nothing else can be.
pub trait Normalize {
  fn normalize(&self) -> Self;
}

/// Implementations of traits for `Const`
impl Debug for Const {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Const::*;
    match *self {
      Data => write!(fmt, "data"),
      Codata => write!(fmt, "codata"),
    }
  }
}

/// Implementations of traits for `Var`
impl Var {
  pub fn new<'input>(name: &'input str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

impl Debug for Var {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    if self.name.len() == 0 {
      Ok(())
    } else if self.idx == 0 {
      write!(fmt, "{}", self.name)
    } else {
      write!(fmt, "{}@{}", self.name, self.idx)
    }
  }
}

/// Implementations of traits for `Expr`
impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }

  pub fn is_constant(&self) -> bool {
    match *self {
      Expr::Const(_) => true,
      _ => false,
    }
  }
  pub fn is_var(&self) -> bool {
    match *self {
      Expr::Var(_) => true,
      _ => false,
    }
  }
  pub fn is_lam(&self) -> bool {
    match *self {
      Expr::Lam(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_pi(&self) -> bool {
    match *self {
      Expr::Pi(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_app(&self) -> bool {
    match *self {
      Expr::App(_, _) => true,
      _ => false,
    }
  }
}

fn replace(val: &Var, with: &Expr, body: &Expr) -> Expr {
  use self::Expr::*;
  // println!("replace {} with {} in {}",
  //          val.to_string(),
  //          with.to_string(),
  //          body.to_string());
  match *body {
    Const(_) => body.clone(),
    Var(ref var) => {
      if *var == *val {
        with.clone()
      } else {
        body.clone()
      }
    }
    Lam(ref var, ref ty, ref body) => {
      if *val == *var {
        // println!("stopping at {}", val.to_string());
        Lam(var.clone(), ty.clone(), body.clone())
      } else {
        let ty = Box::new(replace(val, with, &ty));
        let body = Box::new(replace(val, with, &body));
        let lam = Lam(var.clone(), ty, body);
        // println!("replaced = {}", lam.to_string());
        lam
      }
    }
    Pi(ref var, ref ty, ref body) => {
      if *val == *var {
        // println!("stopping at {}", val.to_string());
        Pi(var.clone(), ty.clone(), body.clone())
      } else {
        let ty = Box::new(replace(val, with, &ty));
        let body = Box::new(replace(val, with, &body));
        let pi = Pi(var.clone(), ty, body);
        // println!("replaced = {}", pi.to_string());
        pi
      }
    }
    App(ref f, ref arg) => {
      let f = Box::new(replace(val, with, &f));
      let arg = Box::new(replace(val, with, &arg));
      let app = App(f, arg);
      // println!("replaced = {}", app.to_string());
      app
    }
  }
}

impl Normalize for Expr {
  fn normalize(&self) -> Expr {
    use self::Expr::*;
    // println!("normalize {}", self.to_string());
    match *self {
      Const(ref constant) => Const(constant.clone()),
      Var(ref var) => Var(var.clone()),
      Lam(ref var, ref ty, ref body) => {
        let l = &Lam(var.clone(),
                     Box::new(ty.normalize()),
                     Box::new(body.normalize()));
        l.clone()
      }
      Pi(ref var, ref ty, ref body) => {
        let p = &Pi(var.clone(),
                    Box::new(ty.normalize()),
                    Box::new(body.normalize()));
        p.clone()
      }
      App(ref f, ref arg) => {
        let f = f.normalize();
        // let f = *f.clone();
        let arg = arg.normalize();
        if let Lam(var, _, body) = f {
          let lam = replace(&var, &arg, &body).normalize();
          // println!("normalized = {}", lam.to_string());
          lam
        } else if let Pi(var, _, body) = f {
          let pi = replace(&var, &arg, &body).normalize();
          // println!("normalized = {}", pi.to_string());
          pi
        } else {
          // panic!("f isn't a function {}", f.to_string())
          App(Box::new(f), Box::new(arg))
        }
      }
    }
  }
}

impl Debug for Expr {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Expr::*;
    match *self {
      Const(ref constant) => write!(fmt, "{:?}", constant),
      Var(ref var) => write!(fmt, "{:?}", var),
      Lam(ref var, ref ty, ref body) => {
        write!(fmt, "\\({:?} : {:?}) -> {:?}", var, ty, body)
      }

      Pi(ref var, ref ty, ref body) => {
        if var.name.len() == 0 {
          write!(fmt, "{:?} -> {:?}", ty, body)
        } else {
          write!(fmt, "forall ({:?} : {:?}) -> {:?}", var, ty, body)
        }
      }
      App(ref f, ref arg) => {
        if f.is_lam() || f.is_pi() {
          try!(write!(fmt, "("))
        } else {
          try!(Ok(()))
        }
        try!(write!(fmt, "{:?}", f));
        if f.is_lam() || f.is_pi() {
          try!(write!(fmt, ")"))
        } else {
          try!(Ok(()))
        }

        try!(write!(fmt, " "));

        if arg.is_lam() || arg.is_pi() || arg.is_app() {
          try!(write!(fmt, "("));
        } else {
          try!(Ok(()));
        }
        try!(write!(fmt, "{:?}", arg));
        if arg.is_lam() || arg.is_pi() || arg.is_app() {
          try!(write!(fmt, ")"))
        } else {
          try!(Ok(()))
        }

        Ok(())
      }
    }
  }
}

/// Implementations of traits for `Def`
impl Normalize for Def {
  fn normalize(&self) -> Def {
    use self::Def::*;
    match *self {
      Val(ref n, ref e) => Def::Val(n.clone(), e.normalize()),
      Ty(ref n, ref t) => Def::Ty(n.clone(), t.normalize()),
    }
  }
}

impl Debug for Def {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Def::*;
    match *self {
      Val(ref n, ref e) => write!(fmt, "{:?} = {:?}.", n, e),
      Ty(ref n, ref t) => write!(fmt, "{:?} : {:?}.", n, t),
    }
  }
}

/// Implementations of traits for `One`
impl Normalize for One {
  fn normalize(&self) -> One {
    use self::One::*;
    match *self {
      Def(ref d) => One::Def(d.normalize()),
      Expr(ref e) => One::Expr(e.normalize()),
    }
  }
}

impl Debug for One {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::One::*;
    match *self {
      Def(ref d) => write!(fmt, "{:?}\n", d),
      Expr(ref e) => write!(fmt, "{:?}.\n", e),
    }
  }
}

/// Implementations of traits for an entire `Mod`
impl Mod {
  pub fn new(listing: Vec<One>) -> Mod {
    Mod { listing: listing }
  }
}

impl Normalize for Mod {
  fn normalize(&self) -> Mod {
    let mut listing = Vec::new();
    for ref o in self.listing.iter() {
      listing.push(o.normalize());
    }
    Mod::new(listing)
  }
}

impl Debug for Mod {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    for ref o in self.listing.iter() {
      try!(write!(fmt, "{:?}", o));
    }
    Ok(())
  }
}

/// Tests for AST
#[cfg(test)]
fn constant(c: Const) -> Expr {
  Expr::constant(c)
}

#[cfg(test)]
fn var(v: &Var) -> Expr {
  Expr::var(v)
}

#[cfg(test)]
fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::lam(var, ty, body)
}

#[cfg(test)]
fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::pi(var, ty, body)
}

#[cfg(test)]
fn app(f: Expr, arg: Expr) -> Expr {
  Expr::app(f, arg)
}

#[test]
fn test_to_string() {
  let codata = Const::Codata;
  assert_eq!("codata", format!("{:?}", codata));
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let expra = var(&a);
  let exprx = var(&x);
  assert_eq!("x", format!("{:?}", x));
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  assert_eq!("forall (a : data) -> \\(x : a) -> x", format!("{:?}", id));
  let apply_id = app(app(id, var(&Var::new("int", 0))), var(&Var::new("1", 0)));
  assert_eq!("(forall (a : data) -> \\(x : a) -> x) int 1",
             format!("{:?}", apply_id));
}

#[test]
fn test_id_eq_id2() {
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let id = Var::new("id", 0);
  let unused = Var::new("", 0);
  // id's type
  let ty = pi(a.clone(),
              constant(Const::Data),
              pi(unused, Expr::var(&a), Expr::var(&a)));
  // id's implementation
  let id_impl = lam(a.clone(),
                    constant(Const::Data),
                    lam(x.clone(), Expr::var(&a), Expr::var(&x)));
  // implementation of id applied to itself applied to id
  let id2app = app(lam(id.clone(),
                       ty.clone(),
                       app(app(Expr::var(&id.clone()), ty.clone()),
                           Expr::var(&id.clone()))),
                   id_impl.clone());
  assert_eq!(id2app.normalize(), id_impl);
}
<commit_msg>Add Def.expr()<commit_after>// Copyright (c) 2016, Matthew O'Connor

//! Abstract syntax tree for System Zero Core
//!
//! Defines AST and traits for debugging and normalizing expressions.

use std::fmt::{Debug, Formatter, Error};

/// `Const` defines the builtin types of types.
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Const {
  /// `Data` is finite and all functions on it must be total.
  Data,
  /// `Codata` is potentially infinite and corecursion must be productive.
  Codata,
}

/// `Var` is the label for a bound variable.
#[derive(Clone, Eq, PartialEq)]
pub struct Var {
  /// `name` is the label.
  name: String,
  /// `idx` is the De Bruijn index, in theory.
  idx: i32,
}

/// `Expr` represents all computations in System Zero Core.
#[derive(Clone, Eq, PartialEq)]
pub enum Expr {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Expr>, Box<Expr>),
  // "forall"
  Pi(Var, Box<Expr>, Box<Expr>),
  // Function application
  App(Box<Expr>, Box<Expr>),
}

/// `Def`s are bindings between `Var` and values or types.
#[derive(Clone, Eq, PartialEq)]
pub enum Def {
  Val(Var, Expr),
  Ty(Var, Expr),
}

/// `One` represents one top-level element. It needs a better name.
#[derive(Clone, Eq, PartialEq)]
pub enum One {
  Def(Def),
  Expr(Expr),
}

/// `Mod` is all of the code for a given module.
#[derive(Clone, Eq, PartialEq)]
pub struct Mod {
  listing: Vec<One>,
}

// # Traits

/// `Normalize` converts the value to a strongly normalized version.
/// Normalization in a total typed lambda calculus is essentially inlining
/// until nothing else can be.
pub trait Normalize {
  fn normalize(&self) -> Self;
}

/// Implementations of traits for `Const`
impl Debug for Const {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Const::*;
    match *self {
      Data => write!(fmt, "data"),
      Codata => write!(fmt, "codata"),
    }
  }
}

/// Implementations of traits for `Var`
impl Var {
  pub fn new<'input>(name: &'input str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

impl Debug for Var {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    if self.name.len() == 0 {
      Ok(())
    } else if self.idx == 0 {
      write!(fmt, "{}", self.name)
    } else {
      write!(fmt, "{}@{}", self.name, self.idx)
    }
  }
}

/// Implementations of traits for `Expr`
impl Expr {
  pub fn constant(constant: Const) -> Expr {
    Expr::Const(constant)
  }
  pub fn var(v: &Var) -> Expr {
    Expr::Var(v.clone())
  }
  pub fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Lam(var, Box::new(ty), Box::new(body))
  }
  pub fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
    Expr::Pi(var, Box::new(ty), Box::new(body))
  }
  pub fn app(f: Expr, arg: Expr) -> Expr {
    Expr::App(Box::new(f), Box::new(arg))
  }

  pub fn is_constant(&self) -> bool {
    match *self {
      Expr::Const(_) => true,
      _ => false,
    }
  }
  pub fn is_var(&self) -> bool {
    match *self {
      Expr::Var(_) => true,
      _ => false,
    }
  }
  pub fn is_lam(&self) -> bool {
    match *self {
      Expr::Lam(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_pi(&self) -> bool {
    match *self {
      Expr::Pi(_, _, _) => true,
      _ => false,
    }
  }
  pub fn is_app(&self) -> bool {
    match *self {
      Expr::App(_, _) => true,
      _ => false,
    }
  }
}

fn replace(val: &Var, with: &Expr, body: &Expr) -> Expr {
  use self::Expr::*;
  // println!("replace {} with {} in {}",
  //          val.to_string(),
  //          with.to_string(),
  //          body.to_string());
  match *body {
    Const(_) => body.clone(),
    Var(ref var) => {
      if *var == *val {
        with.clone()
      } else {
        body.clone()
      }
    }
    Lam(ref var, ref ty, ref body) => {
      if *val == *var {
        // println!("stopping at {}", val.to_string());
        Lam(var.clone(), ty.clone(), body.clone())
      } else {
        let ty = Box::new(replace(val, with, &ty));
        let body = Box::new(replace(val, with, &body));
        let lam = Lam(var.clone(), ty, body);
        // println!("replaced = {}", lam.to_string());
        lam
      }
    }
    Pi(ref var, ref ty, ref body) => {
      if *val == *var {
        // println!("stopping at {}", val.to_string());
        Pi(var.clone(), ty.clone(), body.clone())
      } else {
        let ty = Box::new(replace(val, with, &ty));
        let body = Box::new(replace(val, with, &body));
        let pi = Pi(var.clone(), ty, body);
        // println!("replaced = {}", pi.to_string());
        pi
      }
    }
    App(ref f, ref arg) => {
      let f = Box::new(replace(val, with, &f));
      let arg = Box::new(replace(val, with, &arg));
      let app = App(f, arg);
      // println!("replaced = {}", app.to_string());
      app
    }
  }
}

impl Normalize for Expr {
  fn normalize(&self) -> Expr {
    use self::Expr::*;
    // println!("normalize {}", self.to_string());
    match *self {
      Const(ref constant) => Const(constant.clone()),
      Var(ref var) => Var(var.clone()),
      Lam(ref var, ref ty, ref body) => {
        let l = &Lam(var.clone(),
                     Box::new(ty.normalize()),
                     Box::new(body.normalize()));
        l.clone()
      }
      Pi(ref var, ref ty, ref body) => {
        let p = &Pi(var.clone(),
                    Box::new(ty.normalize()),
                    Box::new(body.normalize()));
        p.clone()
      }
      App(ref f, ref arg) => {
        let f = f.normalize();
        // let f = *f.clone();
        let arg = arg.normalize();
        if let Lam(var, _, body) = f {
          let lam = replace(&var, &arg, &body).normalize();
          // println!("normalized = {}", lam.to_string());
          lam
        } else if let Pi(var, _, body) = f {
          let pi = replace(&var, &arg, &body).normalize();
          // println!("normalized = {}", pi.to_string());
          pi
        } else {
          // panic!("f isn't a function {}", f.to_string())
          App(Box::new(f), Box::new(arg))
        }
      }
    }
  }
}

impl Debug for Expr {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Expr::*;
    match *self {
      Const(ref constant) => write!(fmt, "{:?}", constant),
      Var(ref var) => write!(fmt, "{:?}", var),
      Lam(ref var, ref ty, ref body) => {
        write!(fmt, "\\({:?} : {:?}) -> {:?}", var, ty, body)
      }

      Pi(ref var, ref ty, ref body) => {
        if var.name.len() == 0 {
          write!(fmt, "{:?} -> {:?}", ty, body)
        } else {
          write!(fmt, "forall ({:?} : {:?}) -> {:?}", var, ty, body)
        }
      }
      App(ref f, ref arg) => {
        if f.is_lam() || f.is_pi() {
          try!(write!(fmt, "("))
        } else {
          try!(Ok(()))
        }
        try!(write!(fmt, "{:?}", f));
        if f.is_lam() || f.is_pi() {
          try!(write!(fmt, ")"))
        } else {
          try!(Ok(()))
        }

        try!(write!(fmt, " "));

        if arg.is_lam() || arg.is_pi() || arg.is_app() {
          try!(write!(fmt, "("));
        } else {
          try!(Ok(()));
        }
        try!(write!(fmt, "{:?}", arg));
        if arg.is_lam() || arg.is_pi() || arg.is_app() {
          try!(write!(fmt, ")"))
        } else {
          try!(Ok(()))
        }

        Ok(())
      }
    }
  }
}

/// Implementations of traits for `Def`
impl Def {
  pub fn expr(&self) -> &Expr {
    use self::Def::*;
    match *self {
      Val(_, ref e) => e,
      Ty(_, ref e) => e,
    }
  }
}

impl Normalize for Def {
  fn normalize(&self) -> Def {
    use self::Def::*;
    match *self {
      Val(ref n, ref e) => Def::Val(n.clone(), e.normalize()),
      Ty(ref n, ref t) => Def::Ty(n.clone(), t.normalize()),
    }
  }
}

impl Debug for Def {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::Def::*;
    match *self {
      Val(ref n, ref e) => write!(fmt, "{:?} = {:?}.", n, e),
      Ty(ref n, ref t) => write!(fmt, "{:?} : {:?}.", n, t),
    }
  }
}

/// Implementations of traits for `One`
impl Normalize for One {
  fn normalize(&self) -> One {
    use self::One::*;
    match *self {
      Def(ref d) => One::Def(d.normalize()),
      Expr(ref e) => One::Expr(e.normalize()),
    }
  }
}

impl Debug for One {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    use self::One::*;
    match *self {
      Def(ref d) => write!(fmt, "{:?}\n", d),
      Expr(ref e) => write!(fmt, "{:?}.\n", e),
    }
  }
}

/// Implementations of traits for an entire `Mod`
impl Mod {
  pub fn new(listing: Vec<One>) -> Mod {
    Mod { listing: listing }
  }
}

impl Normalize for Mod {
  fn normalize(&self) -> Mod {
    let mut listing = Vec::new();
    for ref o in self.listing.iter() {
      listing.push(o.normalize());
    }
    Mod::new(listing)
  }
}

impl Debug for Mod {
  fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
    for ref o in self.listing.iter() {
      try!(write!(fmt, "{:?}", o));
    }
    Ok(())
  }
}

/// Tests for AST
#[cfg(test)]
fn constant(c: Const) -> Expr {
  Expr::constant(c)
}

#[cfg(test)]
fn var(v: &Var) -> Expr {
  Expr::var(v)
}

#[cfg(test)]
fn lam(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::lam(var, ty, body)
}

#[cfg(test)]
fn pi(var: Var, ty: Expr, body: Expr) -> Expr {
  Expr::pi(var, ty, body)
}

#[cfg(test)]
fn app(f: Expr, arg: Expr) -> Expr {
  Expr::app(f, arg)
}

#[test]
fn test_to_string() {
  let codata = Const::Codata;
  assert_eq!("codata", format!("{:?}", codata));
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let expra = var(&a);
  let exprx = var(&x);
  assert_eq!("x", format!("{:?}", x));
  let id = pi(a.clone(), constant(Const::Data), lam(x, expra, exprx));
  assert_eq!("forall (a : data) -> \\(x : a) -> x", format!("{:?}", id));
  let apply_id = app(app(id, var(&Var::new("int", 0))), var(&Var::new("1", 0)));
  assert_eq!("(forall (a : data) -> \\(x : a) -> x) int 1",
             format!("{:?}", apply_id));
}

#[test]
fn test_id_eq_id2() {
  let a = Var::new("a", 0);
  let x = Var::new("x", 0);
  let id = Var::new("id", 0);
  let unused = Var::new("", 0);
  // id's type
  let ty = pi(a.clone(),
              constant(Const::Data),
              pi(unused, Expr::var(&a), Expr::var(&a)));
  // id's implementation
  let id_impl = lam(a.clone(),
                    constant(Const::Data),
                    lam(x.clone(), Expr::var(&a), Expr::var(&x)));
  // implementation of id applied to itself applied to id
  let id2app = app(lam(id.clone(),
                       ty.clone(),
                       app(app(Expr::var(&id.clone()), ty.clone()),
                           Expr::var(&id.clone()))),
                   id_impl.clone());
  assert_eq!(id2app.normalize(), id_impl);
}
<|endoftext|>


<commit_before>use crate::helper::{load_module_test, run_top_level_test_with_args};
use serial_test::serial;

#[serial]
#[test]
fn builtins() {
    load_module_test("src/tests/builtins.pl", "");
}

#[serial]
#[test]
fn call_with_inference_limit() {
    load_module_test("src/tests/call_with_inference_limit.pl", "");
}

#[serial]
#[test]
fn facts() {
    load_module_test("src/tests/facts.pl", "");
}

#[serial]
#[test]
fn hello_world() {
    load_module_test("src/tests/hello_world.pl", "Hello World!\n");
}

#[serial]
#[test]
fn syntax_error() {
    load_module_test(
        "tests-pl/syntax_error.pl",
        "caught: error(syntax_error(incomplete_reduction),read_term/3:6)\n",
    );
}

#[serial]
#[test]
fn predicates() {
    load_module_test("src/tests/predicates.pl", "");
}

#[serial]
#[test]
fn rules() {
    load_module_test("src/tests/rules.pl", "");
}

#[serial]
#[test]
fn setup_call_cleanup_load() {
    load_module_test(
        "src/tests/setup_call_cleanup.pl",
        "1+21+31+2>_15388+_153891+_139341+2>41+2>_153891+2>31+2>31+2>4ba"
    );
}

#[test]
fn setup_call_cleanup_process() {
    run_top_level_test_with_args(
        &["src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"],
        "",
        "1+21+31+2>_16835+_168361+_153811+2>41+2>_168361+2>31+2>31+2>4ba"
    );
}

#[serial]
#[test]
fn clpz_load() {
    load_module_test("src/tests/clpz/test_clpz.pl", "");
}
<commit_msg>update setup_call_cleanup tests<commit_after>use crate::helper::{load_module_test, run_top_level_test_with_args};
use serial_test::serial;

#[serial]
#[test]
fn builtins() {
    load_module_test("src/tests/builtins.pl", "");
}

#[serial]
#[test]
fn call_with_inference_limit() {
    load_module_test("src/tests/call_with_inference_limit.pl", "");
}

#[serial]
#[test]
fn facts() {
    load_module_test("src/tests/facts.pl", "");
}

#[serial]
#[test]
fn hello_world() {
    load_module_test("src/tests/hello_world.pl", "Hello World!\n");
}

#[serial]
#[test]
fn syntax_error() {
    load_module_test(
        "tests-pl/syntax_error.pl",
        "caught: error(syntax_error(incomplete_reduction),read_term/3:6)\n",
    );
}

#[serial]
#[test]
fn predicates() {
    load_module_test("src/tests/predicates.pl", "");
}

#[serial]
#[test]
fn rules() {
    load_module_test("src/tests/rules.pl", "");
}

#[serial]
#[test]
fn setup_call_cleanup_load() {
    load_module_test(
        "src/tests/setup_call_cleanup.pl",
        "1+21+31+2>_15785+_157861+_142871+2>41+2>_157861+2>31+2>31+2>4ba"
    );
}

#[test]
fn setup_call_cleanup_process() {
    run_top_level_test_with_args(
        &["src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"],
        "",
        "1+21+31+2>_17278+_172791+_157801+2>41+2>_172791+2>31+2>31+2>4ba"
    );
}

#[serial]
#[test]
fn clpz_load() {
    load_module_test("src/tests/clpz/test_clpz.pl", "");
}
<|endoftext|>


<commit_before>use glium::backend::glutin_backend::GlutinFacade;
use glium::Program;
use super::Config;
use std::fs::File;
use std::io::Read;
use std::error::Error;

#[derive(Clone)]
pub struct GameContext {
    facade: GlutinFacade,
    config: Config, // TODO: we might want to wrap it into `Rc` (performance)
}

impl GameContext {
    pub fn new(facade: GlutinFacade, config: Config) -> Self {
        GameContext {
            facade: facade,
            config: config,
        }
    }

    pub fn get_facade(&self) -> &GlutinFacade {
        &self.facade
    }

    pub fn get_config(&self) -> &Config {
        &self.config
    }

    /// Loads vertex and fragment shader automatically to prevent recompiling
    /// the application
    /// everytime a shader is changed.
    pub fn load_program(&self, shader: &str) -> Result<Program, Box<Error>> {

        let mut vert = try!(File::open(&format!("client/shader/{}.vert", shader)));
        let mut frag = try!(File::open(&format!("client/shader/{}.frag", shader)));

        let mut vert_buf = String::new();
        let mut frag_buf = String::new();

        try!(vert.read_to_string(&mut vert_buf));
        try!(frag.read_to_string(&mut frag_buf));

        let prog = Program::from_source(&self.facade, &vert_buf, &frag_buf, None);
        if let Err(ref e) = prog {
            warn!("failed to compile program '{}':\n{}", shader, e);
        }
        Ok(try!(prog))
    }
}
<commit_msg>Enable loading of tesselation shaders<commit_after>use glium::backend::glutin_backend::GlutinFacade;
use glium::program;
use glium::Program;
use super::Config;
use std::fs::File;
use std::io::{self, Read};
use std::error::Error;

#[derive(Clone)]
pub struct GameContext {
    facade: GlutinFacade,
    config: Config, // TODO: we might want to wrap it into `Rc` (performance)
}

impl GameContext {
    pub fn new(facade: GlutinFacade, config: Config) -> Self {
        GameContext {
            facade: facade,
            config: config,
        }
    }

    pub fn get_facade(&self) -> &GlutinFacade {
        &self.facade
    }

    pub fn get_config(&self) -> &Config {
        &self.config
    }

    /// Loads vertex and fragment shader automatically to prevent recompiling
    /// the application
    /// everytime a shader is changed.
    pub fn load_program(&self, shader: &str) -> Result<Program, Box<Error>> {
        fn load_if_present(path: &str) -> Result<String, io::Error> {
            let mut f = try!(File::open(path));
            let mut buf = String::new();
            try!(f.read_to_string(&mut buf));
            Ok(buf)
        }

        let mut vert = try!(File::open(&format!("client/shader/{}.vert", shader)));
        let mut frag = try!(File::open(&format!("client/shader/{}.frag", shader)));

        let mut vert_buf = String::new();
        let mut frag_buf = String::new();
        try!(vert.read_to_string(&mut vert_buf));
        try!(frag.read_to_string(&mut frag_buf));

        let mut tcs = load_if_present(&format!("client/shader/{}.tcs", shader)).ok();
        let mut tes = load_if_present(&format!("client/shader/{}.tes", shader)).ok();

        let source = program::SourceCode {
            vertex_shader: &vert_buf,
            tessellation_control_shader: tcs.as_ref().map(|s| s.as_str()),
            tessellation_evaluation_shader: tes.as_ref().map(|s| s.as_str()),
            geometry_shader: None,
            fragment_shader: &frag_buf,
        };

        let prog = Program::new(&self.facade, source);

        if let Err(ref e) = prog {
            warn!("failed to compile program '{}':\n{}", shader, e);
        }
        Ok(try!(prog))
    }
}
<|endoftext|>


<commit_before>#![allow(clippy::filter_map)]

use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;

// This module takes an absolute path to a rustc repo and alters the dependencies to point towards
// the respective rustc subcrates instead of using extern crate xyz.
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details

pub fn run(rustc_path: Option<&str>) {
    // we can unwrap here because the arg is required here
    let rustc_path = PathBuf::from(rustc_path.unwrap());
    assert!(rustc_path.is_dir(), "path is not a directory");
    let rustc_source_basedir = rustc_path.join("src");
    assert!(
        rustc_source_basedir.is_dir(),
        "are you sure the path leads to a rustc repo?"
    );

    let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml");
    let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs");
    inject_deps_into_manifest(
        &rustc_source_basedir,
        "Cargo.toml",
        &clippy_root_manifest,
        &clippy_root_lib_rs,
    )
    .expect("Failed to inject deps into ./Cargo.toml");

    let clippy_lints_manifest =
        fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml");
    let clippy_lints_lib_rs =
        fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs");
    inject_deps_into_manifest(
        &rustc_source_basedir,
        "clippy_lints/Cargo.toml",
        &clippy_lints_manifest,
        &clippy_lints_lib_rs,
    )
    .expect("Failed to inject deps into ./clippy_lints/Cargo.toml");
}

fn inject_deps_into_manifest(
    rustc_source_dir: &PathBuf,
    manifest_path: &str,
    cargo_toml: &str,
    lib_rs: &str,
) -> std::io::Result<()> {
    let extern_crates = lib_rs
        .lines()
        // get the deps
        .filter(|line| line.starts_with("extern crate"))
        // we have something like "extern crate foo;", we only care about the "foo"
        //              ↓          ↓
        // extern crate rustc_middle;
        .map(|s| &s[13..(s.len() - 1)]);

    let new_deps = extern_crates.map(|dep| {
        // format the dependencies that are going to be put inside the Cargo.toml
        format!(
            "{dep} = {{ path = \"{source_path}/lib{dep}\" }}\n",
            dep = dep,
            source_path = rustc_source_dir.display()
        )
    });

    // format a new [dependencies]-block with the new deps we need to inject
    let mut all_deps = String::from("[dependencies]\n");
    new_deps.for_each(|dep_line| {
        all_deps.push_str(&dep_line);
    });

    // replace "[dependencies]" with
    // [dependencies]
    // dep1 = { path = ... }
    // dep2 = { path = ... }
    // etc
    let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);

    // println!("{}", new_manifest);
    let mut file = File::create(manifest_path)?;
    file.write_all(new_manifest.as_bytes())?;

    println!("Dependency paths injected: {}", manifest_path);

    Ok(())
}
<commit_msg>Prevent compile parts of rustc when using `cargo dev ra-setup`<commit_after>#![allow(clippy::filter_map)]

use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;

// This module takes an absolute path to a rustc repo and alters the dependencies to point towards
// the respective rustc subcrates instead of using extern crate xyz.
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details

pub fn run(rustc_path: Option<&str>) {
    // we can unwrap here because the arg is required here
    let rustc_path = PathBuf::from(rustc_path.unwrap());
    assert!(rustc_path.is_dir(), "path is not a directory");
    let rustc_source_basedir = rustc_path.join("src");
    assert!(
        rustc_source_basedir.is_dir(),
        "are you sure the path leads to a rustc repo?"
    );

    let clippy_root_manifest = fs::read_to_string("Cargo.toml").expect("failed to read ./Cargo.toml");
    let clippy_root_lib_rs = fs::read_to_string("src/driver.rs").expect("failed to read ./src/driver.rs");
    inject_deps_into_manifest(
        &rustc_source_basedir,
        "Cargo.toml",
        &clippy_root_manifest,
        &clippy_root_lib_rs,
    )
    .expect("Failed to inject deps into ./Cargo.toml");

    let clippy_lints_manifest =
        fs::read_to_string("clippy_lints/Cargo.toml").expect("failed to read ./clippy_lints/Cargo.toml");
    let clippy_lints_lib_rs =
        fs::read_to_string("clippy_lints/src/lib.rs").expect("failed to read ./clippy_lints/src/lib.rs");
    inject_deps_into_manifest(
        &rustc_source_basedir,
        "clippy_lints/Cargo.toml",
        &clippy_lints_manifest,
        &clippy_lints_lib_rs,
    )
    .expect("Failed to inject deps into ./clippy_lints/Cargo.toml");
}

fn inject_deps_into_manifest(
    rustc_source_dir: &PathBuf,
    manifest_path: &str,
    cargo_toml: &str,
    lib_rs: &str,
) -> std::io::Result<()> {
    let extern_crates = lib_rs
        .lines()
        // get the deps
        .filter(|line| line.starts_with("extern crate"))
        // we have something like "extern crate foo;", we only care about the "foo"
        //              ↓          ↓
        // extern crate rustc_middle;
        .map(|s| &s[13..(s.len() - 1)]);

    let new_deps = extern_crates.map(|dep| {
        // format the dependencies that are going to be put inside the Cargo.toml
        format!(
            "{dep} = {{ path = \"{source_path}/lib{dep}\" }}\n",
            dep = dep,
            source_path = rustc_source_dir.display()
        )
    });

    // format a new [dependencies]-block with the new deps we need to inject
    let mut all_deps = String::from("[target.'cfg(NOT_A_PLATFORM)'.dependencies]\n");
    new_deps.for_each(|dep_line| {
        all_deps.push_str(&dep_line);
    });
    all_deps.push_str("\n[dependencies]\n");

    // replace "[dependencies]" with
    // [dependencies]
    // dep1 = { path = ... }
    // dep2 = { path = ... }
    // etc
    let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);

    // println!("{}", new_manifest);
    let mut file = File::create(manifest_path)?;
    file.write_all(new_manifest.as_bytes())?;

    println!("Dependency paths injected: {}", manifest_path);

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::path::{Path, PathBuf};

use users;

use env as henv;

/// The default filesystem root path
pub const FS_ROOT_PATH: &'static str = "/";
/// The default root path of the Habitat filesytem
pub const ROOT_PATH: &'static str = "hab";
/// The default path for any analytics related files
pub const CACHE_ANALYTICS_PATH: &'static str = "hab/cache/analytics";
/// The default download root path for package artifacts, used on package installation
pub const CACHE_ARTIFACT_PATH: &'static str = "hab/cache/artifacts";
/// The default path where cryptographic keys are stored
pub const CACHE_KEY_PATH: &'static str = "hab/cache/keys";
/// The default path where source artifacts are downloaded, extracted, & compiled
pub const CACHE_SRC_PATH: &'static str = "hab/cache/src";
/// The default path where SSL-related artifacts are placed
pub const CACHE_SSL_PATH: &'static str = "hab/cache/ssl";
/// The root path containing all locally installed packages
pub const PKG_PATH: &'static str = "hab/pkgs";
/// The root path containing all runtime service directories and files
const SVC_PATH: &'static str = "hab/svc";

lazy_static! {
    static ref EUID: u32 = users::get_effective_uid();

    static ref MY_CACHE_ANALYTICS_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_ANALYTICS_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_ANALYTICS_PATH)),
                None => PathBuf::from(CACHE_ANALYTICS_PATH),
            }
        }
    };

    static ref MY_CACHE_ARTIFACT_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_ARTIFACT_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_ARTIFACT_PATH)),
                None => PathBuf::from(CACHE_ARTIFACT_PATH),
            }
        }
    };

    static ref MY_CACHE_KEY_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_KEY_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_KEY_PATH)),
                None => PathBuf::from(CACHE_KEY_PATH),
            }
        }
    };

    static ref MY_CACHE_SRC_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_SRC_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_SRC_PATH)),
                None => PathBuf::from(CACHE_SRC_PATH),
            }
        }
    };

    static ref MY_CACHE_SSL_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_SSL_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_SSL_PATH)),
                None => PathBuf::from(CACHE_SSL_PATH),
            }
        }
    };
}

/// Returns the path to the analytics cache, optionally taking a custom filesystem root.
pub fn cache_analytics_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_ANALYTICS_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_ANALYTICS_PATH),
    }
}

/// Returns the path to the artifacts cache, optionally taking a custom filesystem root.
pub fn cache_artifact_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_ARTIFACT_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_ARTIFACT_PATH),
    }
}

/// Returns the path to the keys cache, optionally taking a custom filesystem root.
pub fn cache_key_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_KEY_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_KEY_PATH),
    }
}

/// Returns the path to the src cache, optionally taking a custom filesystem root.
pub fn cache_src_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_SRC_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_SRC_PATH),
    }
}

/// Returns the path to the SSL cache, optionally taking a custom filesystem root.
pub fn cache_ssl_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_SSL_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_SSL_PATH),
    }
}

/// Returns the root path containing all runtime service directories and files
pub fn svc_root() -> PathBuf {
    Path::new("/").join(SVC_PATH).to_path_buf()
}

/// Returns the root path for a given service's configuration, files, and data.
pub fn svc_path(service_name: &str) -> PathBuf {
    Path::new("/").join(SVC_PATH).join(service_name)
}

/// Returns the path to a given service's configuration.
pub fn svc_config_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("config")
}

/// Returns the path to a given service's data.
pub fn svc_data_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("data")
}

/// Returns the path to a given service's gossiped config files.
pub fn svc_files_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("files")
}

/// Returns the path to a given service's hooks.
///
/// Note that this path is internal to the Supervisor and should not be directly accessed under
/// normal circumstances.
pub fn svc_hooks_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("hooks")
}

/// Returns the path to a given service's static content.
pub fn svc_static_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("static")
}

/// Returns the path to a given service's variable state.
pub fn svc_var_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("var")
}

/// Returns the absolute path for a given command, if it exists, by searching the `PATH`
/// environment variable.
///
/// If the command represents an absolute path, then the `PATH` seaching will not be performed. If
/// no absolute path can be found for the command, then `None` is returned.
pub fn find_command(command: &str) -> Option<PathBuf> {
    // If the command path is absolute and a file exists, then use that.
    let candidate = PathBuf::from(command);
    if candidate.is_absolute() && candidate.is_file() {
        return Some(candidate);
    }

    // Find the command by checking each entry in `PATH`. If we still can't find it, give up and
    // return `None`.
    match henv::var_os("PATH") {
        Some(paths) => {
            for path in env::split_paths(&paths) {
                let candidate = PathBuf::from(&path).join(command);
                if candidate.is_file() {
                    return Some(candidate);
                }
            }
            None
        }
        None => None,
    }
}

/// Returns whether or not the current process is running with a root effective user id or not.
pub fn am_i_root() -> bool {
    *EUID == 0u32
}
<commit_msg>Support windows command resolution<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::path::{Path, PathBuf};

use users;

use env as henv;

/// The default filesystem root path
pub const FS_ROOT_PATH: &'static str = "/";
/// The default root path of the Habitat filesytem
pub const ROOT_PATH: &'static str = "hab";
/// The default path for any analytics related files
pub const CACHE_ANALYTICS_PATH: &'static str = "hab/cache/analytics";
/// The default download root path for package artifacts, used on package installation
pub const CACHE_ARTIFACT_PATH: &'static str = "hab/cache/artifacts";
/// The default path where cryptographic keys are stored
pub const CACHE_KEY_PATH: &'static str = "hab/cache/keys";
/// The default path where source artifacts are downloaded, extracted, & compiled
pub const CACHE_SRC_PATH: &'static str = "hab/cache/src";
/// The default path where SSL-related artifacts are placed
pub const CACHE_SSL_PATH: &'static str = "hab/cache/ssl";
/// The root path containing all locally installed packages
pub const PKG_PATH: &'static str = "hab/pkgs";
/// The root path containing all runtime service directories and files
const SVC_PATH: &'static str = "hab/svc";

lazy_static! {
    static ref EUID: u32 = users::get_effective_uid();

    static ref MY_CACHE_ANALYTICS_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_ANALYTICS_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_ANALYTICS_PATH)),
                None => PathBuf::from(CACHE_ANALYTICS_PATH),
            }
        }
    };

    static ref MY_CACHE_ARTIFACT_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_ARTIFACT_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_ARTIFACT_PATH)),
                None => PathBuf::from(CACHE_ARTIFACT_PATH),
            }
        }
    };

    static ref MY_CACHE_KEY_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_KEY_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_KEY_PATH)),
                None => PathBuf::from(CACHE_KEY_PATH),
            }
        }
    };

    static ref MY_CACHE_SRC_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_SRC_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_SRC_PATH)),
                None => PathBuf::from(CACHE_SRC_PATH),
            }
        }
    };

    static ref MY_CACHE_SSL_PATH: PathBuf = {
        if *EUID == 0u32 {
            PathBuf::from(CACHE_SSL_PATH)
        } else {
            match env::home_dir() {
                Some(home) => home.join(format!(".{}", CACHE_SSL_PATH)),
                None => PathBuf::from(CACHE_SSL_PATH),
            }
        }
    };
}

/// Returns the path to the analytics cache, optionally taking a custom filesystem root.
pub fn cache_analytics_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_ANALYTICS_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_ANALYTICS_PATH),
    }
}

/// Returns the path to the artifacts cache, optionally taking a custom filesystem root.
pub fn cache_artifact_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_ARTIFACT_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_ARTIFACT_PATH),
    }
}

/// Returns the path to the keys cache, optionally taking a custom filesystem root.
pub fn cache_key_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_KEY_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_KEY_PATH),
    }
}

/// Returns the path to the src cache, optionally taking a custom filesystem root.
pub fn cache_src_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_SRC_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_SRC_PATH),
    }
}

/// Returns the path to the SSL cache, optionally taking a custom filesystem root.
pub fn cache_ssl_path(fs_root_path: Option<&Path>) -> PathBuf {
    match fs_root_path {
        Some(fs_root_path) => Path::new(fs_root_path).join(&*MY_CACHE_SSL_PATH),
        None => Path::new(FS_ROOT_PATH).join(&*MY_CACHE_SSL_PATH),
    }
}

/// Returns the root path containing all runtime service directories and files
pub fn svc_root() -> PathBuf {
    Path::new("/").join(SVC_PATH).to_path_buf()
}

/// Returns the root path for a given service's configuration, files, and data.
pub fn svc_path(service_name: &str) -> PathBuf {
    Path::new("/").join(SVC_PATH).join(service_name)
}

/// Returns the path to a given service's configuration.
pub fn svc_config_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("config")
}

/// Returns the path to a given service's data.
pub fn svc_data_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("data")
}

/// Returns the path to a given service's gossiped config files.
pub fn svc_files_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("files")
}

/// Returns the path to a given service's hooks.
///
/// Note that this path is internal to the Supervisor and should not be directly accessed under
/// normal circumstances.
pub fn svc_hooks_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("hooks")
}

/// Returns the path to a given service's static content.
pub fn svc_static_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("static")
}

/// Returns the path to a given service's variable state.
pub fn svc_var_path(service_name: &str) -> PathBuf {
    svc_path(service_name).join("var")
}

/// Returns the absolute path for a given command, if it exists, by searching the `PATH`
/// environment variable.
///
/// If the command represents an absolute path, then the `PATH` seaching will not be performed. If
/// no absolute path can be found for the command, then `None` is returned.
pub fn find_command(command: &str) -> Option<PathBuf> {
    // If the command path is absolute and a file exists, then use that.
    let candidate = PathBuf::from(command);
    if candidate.is_absolute() && candidate.is_file() {
        return Some(candidate);
    }

    // Find the command by checking each entry in `PATH`. If we still can't find it, give up and
    // return `None`.
    match henv::var_os("PATH") {
        Some(paths) => {
            for path in env::split_paths(&paths) {
                let candidate = PathBuf::from(&path).join(command);
                if candidate.is_file() {
                    return Some(candidate);
                }
                else {
                    match find_command_with_pathext(&candidate) {
                        Some(result) => return Some(result),
                        None => {}
                    }
                }
            }
            None
        }
        None => None,
    }
}

// Windows relies on path extensions to resolve commands like `docker` to `docker.exe`
// Path extensions are found in the PATHEXT environment variable.
fn find_command_with_pathext(candidate: &PathBuf) -> Option<PathBuf> {
    match henv::var_os("PATHEXT") {
        Some(pathexts) => {
            for pathext in env::split_paths(&pathexts) {
                let mut source_candidate = candidate.to_path_buf();
                let extension = pathext.to_str().unwrap().trim_matches('.');
                source_candidate.set_extension(extension);
                let current_candidate = source_candidate.to_path_buf();
                if current_candidate.is_file() {
                    return Some(current_candidate);
                }
            }
        },
        None => return None,
    };
    None
}

/// Returns whether or not the current process is running with a root effective user id or not.
pub fn am_i_root() -> bool {
    *EUID == 0u32
}
<|endoftext|>


<commit_before>//! This module contains neural network implementations.
extern crate collenchyma as co;
extern crate collenchyma_nn as nn;
use co::prelude::*;
use nn::*;
use super::{SISO, Learning};
<commit_msg>fixed collenchyma uses<commit_after>//! This module contains neural network implementations.
extern crate collenchyma as co;
extern crate collenchyma_nn as nn;
use self::co::backend::{Backend, BackendConfig};
use self::co::framework::IFramework;
use self::co::frameworks::{Cuda, Native};
use self::co::memory::MemoryType;
use self::co::tensor::SharedTensor;
use self::nn::*;
use super::{SISO, Learning};
<|endoftext|>


<commit_before>/*
rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
*/

macro_rules! namespace{
    ( $name:ident : $base:expr {
        $( $sub:ident: $sub_name:expr),+
    }) => (
        pub mod $name{
            pub static BASE: &'static str = $base;
            $(

                pub static $sub : &'static str = concat!($base, $sub_name);
            )+
        }
    )
}

namespace!{
    rdfs: "http://www.w3.org/2000/01/rdf-schema#"{
        CLASS: "Class",
        DATATYPE: "Datatype"
    }
}
namespace!{
    rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#"{
        TYPE:          "type",
        HTML:          "HTML",
        LANG_STRING:   "langString",
        PLAINLITERAL:  "PlainLiteral",
        PROPERTY:      "Property",
        STATEMENT:     "Statement",
        SUBJECT:       "subject",
        PREDICATE:     "predicate",
        OBJECT:        "object",
        BAG:           "Bag",
        SEQ:           "Seq",
        ALT:           "Alt",
        VALUE:         "value",
        LIST:          "List",
        NIL:           "nil",
        FIRST:         "first",
        REST:          "rest",
        XMLLITERAL:    "XMLLiteral"
    }
}
<commit_msg>Add some namespace related functions and complete rdfs<commit_after>/*
rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
rdfs: "http://www.w3.org/2000/01/rdf-schema#"
*/

macro_rules! namespace{
    (
        $($name:ident : $base:expr {
            $( $sub:ident: $sub_name:expr),+
        })*
    ) => (
        $(pub mod $name{
            pub static BASE: &'static str = $base;
            $(
                pub static $sub : &'static str = concat!($base, $sub_name);
            )+
        })*
        fn full_uri(prefix: &str, suffix: &str) -> Option<&'static str>{
            match (prefix, suffix){
                $(
                    $(
                        (stringify!($name), $sub_name) => Some($name::$sub),
                    )+
                )*
                _ => None
            }
        }
        fn prefixed(full: &str) -> Option<(&'static str, &'static str)>{
            match full{
                $(
                    $(
                        concat!($base, $sub_name) => Some((stringify!($name), $sub_name)),
                    )+
                )*
                _ => None
            }
        }
    )
}

namespace!{
    rdfs: "http://www.w3.org/2000/01/rdf-schema#"{
        CLASS:           "Class",
        DATATYPE:        "Datatype",
        RESOURCE:        "Resource",
        SUB_CLASS_OF:    "subClassOf",
        SUB_PROPERTY_OF: "subPropertyOf",
        COMMENT:         "comment",
        LABEL:           "label",
        DOMAIN:          "domain",
        RANGE:           "range",
        SEE_ALSO:        "seeAlso",
        IS_DEFINED_BY:   "isDefinedBy",
        LITERAL:         "Literal",
        CONTAINER:       "Container",
        MEMBER:          "member",
        CONTAINER_MEMBERSHIP_PROPERTY: "ContainerMembershipProperty"
    }
    rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#"{
        TYPE:          "type",
        HTML:          "HTML",
        LANG_STRING:   "langString",
        PLAIN_LITERAL: "PlainLiteral",
        PROPERTY:      "Property",
        STATEMENT:     "Statement",
        SUBJECT:       "subject",
        PREDICATE:     "predicate",
        OBJECT:        "object",
        BAG:           "Bag",
        SEQ:           "Seq",
        ALT:           "Alt",
        VALUE:         "value",
        LIST:          "List",
        NIL:           "nil",
        FIRST:         "first",
        REST:          "rest",
        XMLLITERAL:    "XMLLiteral"
    }
}

#[test]
fn test_prefix(){
    assert_eq!(full_uri("rdf","Property"), Some(rdf::PROPERTY));
    assert_eq!(prefixed(rdf::PROPERTY), Some(("rdf","Property")));
}
<|endoftext|>