<commit_before>use std::sync::Arc;
use std::cmp;

use {Point2f, Vector3f};
use bsdf::{self, BxDFType};
use spectrum::Spectrum;
use interaction::SurfaceInteraction;
use light::{is_delta_light, Light};
use light_arena::Allocator;
use ray::{Ray, RayDifferential};
use sampler::Sampler;
use sampling::{power_heuristic, Distribution1D};
use scene::Scene;

mod whitted;
mod directlighting;
mod path;
mod ao;
mod normal;

pub use self::whitted::Whitted;
pub use self::directlighting::{DirectLightingIntegrator, LightStrategy};
pub use self::path::PathIntegrator;
pub use self::ao::AmbientOcclusion;
pub use self::normal::Normal;

pub trait SamplerIntegrator {
    fn preprocess(&mut self, _scene: &Scene, _sampler: &mut Box<Sampler + Send + Sync>) {}

    fn li(
        &self,
        scene: &Scene,
        ray: &mut Ray,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum;

    #[allow(non_snake_case)]
    fn specular_reflection(
        &self,
        ray: &mut Ray,
        isect: &SurfaceInteraction,
        scene: &Scene,
        bsdf: &bsdf::BSDF,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum {
        let flags = BxDFType::BSDF_REFLECTION | BxDFType::BSDF_SPECULAR;
        let (f, wi, pdf, _bsdf_type) = bsdf.sample_f(&isect.wo, &sampler.get_2d(), flags);
        let ns = &isect.shading.n;
        if pdf > 0.0 && !f.is_black() && wi.dotn(ns).abs() != 0.0 {
            let mut r = isect.spawn_ray(&wi);
            if let Some(diff) = ray.differential {
                let mut rddiff = RayDifferential::default();
                rddiff.rx_origin = isect.p + isect.dpdx;
                rddiff.ry_origin = isect.p + isect.dpdy;
                // Compute differential reflected direction
                let dndx = isect.shading.dndu * isect.dudx + isect.dndv * isect.dvdx;
                let dndy = isect.shading.dndu * isect.dudy + isect.dndv * isect.dvdy;
                let dwodx = -diff.rx_direction - isect.wo;
                let dwody = -diff.ry_direction - isect.wo;
                let dDNdx = dwodx.dotn(ns) + isect.wo.dotn(&dndx);
                let dDNdy = dwody.dotn(ns) + isect.wo.dotn(&dndy);
                rddiff.rx_direction =
                    wi - dwodx + 2.0 * Vector3f::from(isect.wo.dotn(ns) * dndx + dDNdx * *ns);
                rddiff.ry_direction =
                    wi - dwody + 2.0 * Vector3f::from(isect.wo.dotn(ns) * dndy + dDNdy * *ns);

                r.differential = Some(rddiff);
            }
            let refl = self.li(scene, &mut r, sampler, arena, depth + 1);
            f * refl * wi.dotn(ns).abs() / pdf
        } else {
            Spectrum::black()
        }
    }

    #[allow(non_snake_case)]
    fn specular_transmission(
        &self,
        ray: &mut Ray,
        isect: &SurfaceInteraction,
        scene: &Scene,
        bsdf: &bsdf::BSDF,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum {
        let flags = BxDFType::BSDF_TRANSMISSION | BxDFType::BSDF_SPECULAR;
        let (f, wi, pdf, _bsdf_type) = bsdf.sample_f(&isect.wo, &sampler.get_2d(), flags);
        let ns = &isect.shading.n;
        if pdf > 0.0 && !f.is_black() && wi.dotn(ns).abs() != 0.0 {
            let mut r = isect.spawn_ray(&wi);
            if let Some(diff) = ray.differential {
                let mut rddiff = RayDifferential::default();
                rddiff.rx_origin = isect.p + isect.dpdx;
                rddiff.ry_origin = isect.p + isect.dpdy;

                let mut eta = bsdf.eta;
                let w = -isect.wo;
                if isect.wo.dotn(ns) < 0.0 {
                    eta = 1.0 / eta;
                }

                // Compute differential reflected direction
                let dndx = isect.shading.dndu * isect.dudx + isect.dndv * isect.dvdx;
                let dndy = isect.shading.dndu * isect.dudy + isect.dndv * isect.dvdy;
                let dwodx = -diff.rx_direction - isect.wo;
                let dwody = -diff.ry_direction - isect.wo;
                let dDNdx = dwodx.dotn(ns) + isect.wo.dotn(&dndx);
                let dDNdy = dwody.dotn(ns) + isect.wo.dotn(&dndy);

                let mu = eta * w.dotn(ns) - wi.dotn(ns);
                let dmudx = (eta - (eta * eta * w.dotn(ns)) / wi.dotn(ns)) * dDNdx;
                let dmudy = (eta - (eta * eta * w.dotn(ns)) / wi.dotn(ns)) * dDNdy;

                rddiff.rx_direction = wi + eta * dwodx - Vector3f::from(mu * dndx + dDNdx * *ns);
                rddiff.ry_direction = wi + eta * dwody - Vector3f::from(mu * dndy + dDNdy * *ns);

                r.differential = Some(rddiff);
            }
            let refr = self.li(scene, &mut r, sampler, arena, depth + 1);
            f * refr * wi.dotn(ns).abs() / pdf
        } else {
            Spectrum::black()
        }
    }
}

pub fn uniform_sample_all_light(
    it: &SurfaceInteraction,
    scene: &Scene,
    sampler: &mut Box<Sampler + Send + Sync>,
    n_light_samples: &[usize],
) -> Spectrum {
    let mut L = Spectrum::black();
    for j in 0..scene.lights.len() {
        // Accumulate contribution of j_th light to L
        let light = &scene.lights[j];
        let n_samples = n_light_samples[j];
        // FIXME find a way to not copy the arrays into a vec...
        let u_light_array = sampler.get_2d_array(n_samples).map(|a| a.to_vec());
        let u_scattering_array = sampler.get_2d_array(n_samples).map(|a| a.to_vec());
        if u_scattering_array.is_none() || u_light_array.is_none() {
            // Use a single sample for illumination from light
            let u_light = sampler.get_2d();
            let u_scattering = sampler.get_2d();
            L += estimate_direct(it, &u_scattering, light, &u_light, scene, sampler);
        } else {
            let u_light_array = u_light_array.unwrap();
            let u_scattering_array = u_scattering_array.unwrap();
            let mut Ld = Spectrum::black();
            for k in 0..n_samples {
                Ld += estimate_direct(
                    it,
                    &u_scattering_array[k],
                    light,
                    &u_light_array[k],
                    scene,
                    sampler,
                );
            }
            L += Ld;
        }
    }

    L
}

pub fn uniform_sample_one_light<'a, D: Into<Option<&'a Distribution1D>>>(
    it: &SurfaceInteraction,
    scene: &Scene,
    sampler: &mut Box<Sampler + Send + Sync>,
    distrib: D,
) -> Spectrum {
    let distrib = distrib.into();
    let n_lights = scene.lights.len();
    if n_lights == 0 {
        Spectrum::black()
    } else {
        // Randomly chose a light to sample
        let s = sampler.get_1d();
        let (light_num, light_pdf) = match distrib {
            Some(distrib) => distrib.sample_discrete(s),
            None => (
                cmp::min(n_lights - 1, (s * n_lights as f32) as usize),
                1.0 / n_lights as f32,
            ),
        };

        debug!(
            "sampler.get_1d()={}, n_lights={}, light_num={}, light_pdf={}",
            s,
            n_lights,
            light_num,
            light_pdf
        );

        if light_pdf == 0.0 {
            return Spectrum::black();
        }
        let light = &scene.lights[light_num];
        let u_light = sampler.get_2d();
        let u_scattering = sampler.get_2d();
        estimate_direct(it, &u_scattering, light, &u_light, scene, sampler) / light_pdf
    }
}

pub fn estimate_direct(
    it: &SurfaceInteraction,
    u_scattering: &Point2f,
    light: &Arc<Light + Send + Sync>,
    u_light: &Point2f,
    scene: &Scene,
    _sampler: &mut Box<Sampler + Send + Sync>,
) -> Spectrum {
    let specular = false;

    let bsdf_flags = if specular {
        BxDFType::all()
    } else {
        BxDFType::all() & !BxDFType::BSDF_SPECULAR
    };
    let mut ld = Spectrum::black();
    // Sample light with multiple importance sampling
    let bsdf = it.bsdf
        .as_ref()
        .expect("There should be a BSDF set at this point!");
    let (mut li, wi, light_pdf, vis) = light.sample_li(it, u_light);
    if light_pdf > 0.0 && !li.is_black() {
        // Compute BSDF for light sample
        let f = bsdf.f(&it.wo, &wi, bsdf_flags) * wi.dotn(&it.shading.n).abs();
        let scattering_pdf = bsdf.pdf(&it.wo, &wi, bsdf_flags);
        if !f.is_black() {
            if !vis.unoccluded(scene) {
                li = Spectrum::black();
            }
            // Add light's contribution to reflected radiance
            if !li.is_black() {
                if is_delta_light(light.flags()) {
                    ld += f * li / light_pdf;
                } else {
                    let weight = power_heuristic(1, light_pdf, 1, scattering_pdf);
                    ld += f * li * weight / light_pdf;
                }
            }
        }
        // TODO compute phase function for medium interaction when supported
    }
    // Sample BSDF with multiple importance sampling
    if !is_delta_light(light.flags()) {
        let (mut f, wi, scattering_pdf, sampled_type) =
            bsdf.sample_f(&it.wo, u_scattering, bsdf_flags);
        f = f * wi.dotn(&it.shading.n).abs();
        let sampled_specular = sampled_type.contains(BxDFType::BSDF_SPECULAR);
        // TODO compute medium interaction when supported
        if !f.is_black() && scattering_pdf > 0.0 {
            // Account for light contribution along sampled direction wi
            let weight = if !sampled_specular {
                let light_pdf = light.pdf_li(it, &wi);
                if light_pdf == 0.0 {
                    return ld;
                }
                power_heuristic(1, scattering_pdf, 1, light_pdf)
            } else {
                1.0
            };

            // Find intersection and compute transmittance
            let mut ray = it.spawn_ray(&wi);
            let li = match scene.intersect(&mut ray) {
                Some(light_isect) => {
                    // Add light contribution from material sampling
                    if let Some(area_light) = light_isect.primitive.and_then(|p| p.area_light()) {
                        if area_light.id() == light.id() {
                            light_isect.le(&(-wi))
                        } else {
                            Spectrum::black()
                        }
                    } else {
                        Spectrum::black()
                    }
                }
                None => light.le(&ray),
            };
            if !li.is_black() {
                ld += f * li * weight / scattering_pdf;
            }
        }
    }

    ld
}
<commit_msg>Fix small calculation error in uniform_sample_all_light()<commit_after>use std::sync::Arc;
use std::cmp;

use {Point2f, Vector3f};
use bsdf::{self, BxDFType};
use spectrum::Spectrum;
use interaction::SurfaceInteraction;
use light::{is_delta_light, Light};
use light_arena::Allocator;
use ray::{Ray, RayDifferential};
use sampler::Sampler;
use sampling::{power_heuristic, Distribution1D};
use scene::Scene;

mod whitted;
mod directlighting;
mod path;
mod ao;
mod normal;

pub use self::whitted::Whitted;
pub use self::directlighting::{DirectLightingIntegrator, LightStrategy};
pub use self::path::PathIntegrator;
pub use self::ao::AmbientOcclusion;
pub use self::normal::Normal;

pub trait SamplerIntegrator {
    fn preprocess(&mut self, _scene: &Scene, _sampler: &mut Box<Sampler + Send + Sync>) {}

    fn li(
        &self,
        scene: &Scene,
        ray: &mut Ray,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum;

    #[allow(non_snake_case)]
    fn specular_reflection(
        &self,
        ray: &mut Ray,
        isect: &SurfaceInteraction,
        scene: &Scene,
        bsdf: &bsdf::BSDF,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum {
        let flags = BxDFType::BSDF_REFLECTION | BxDFType::BSDF_SPECULAR;
        let (f, wi, pdf, _bsdf_type) = bsdf.sample_f(&isect.wo, &sampler.get_2d(), flags);
        let ns = &isect.shading.n;
        if pdf > 0.0 && !f.is_black() && wi.dotn(ns).abs() != 0.0 {
            let mut r = isect.spawn_ray(&wi);
            if let Some(diff) = ray.differential {
                let mut rddiff = RayDifferential::default();
                rddiff.rx_origin = isect.p + isect.dpdx;
                rddiff.ry_origin = isect.p + isect.dpdy;
                // Compute differential reflected direction
                let dndx = isect.shading.dndu * isect.dudx + isect.dndv * isect.dvdx;
                let dndy = isect.shading.dndu * isect.dudy + isect.dndv * isect.dvdy;
                let dwodx = -diff.rx_direction - isect.wo;
                let dwody = -diff.ry_direction - isect.wo;
                let dDNdx = dwodx.dotn(ns) + isect.wo.dotn(&dndx);
                let dDNdy = dwody.dotn(ns) + isect.wo.dotn(&dndy);
                rddiff.rx_direction =
                    wi - dwodx + 2.0 * Vector3f::from(isect.wo.dotn(ns) * dndx + dDNdx * *ns);
                rddiff.ry_direction =
                    wi - dwody + 2.0 * Vector3f::from(isect.wo.dotn(ns) * dndy + dDNdy * *ns);

                r.differential = Some(rddiff);
            }
            let refl = self.li(scene, &mut r, sampler, arena, depth + 1);
            f * refl * wi.dotn(ns).abs() / pdf
        } else {
            Spectrum::black()
        }
    }

    #[allow(non_snake_case)]
    fn specular_transmission(
        &self,
        ray: &mut Ray,
        isect: &SurfaceInteraction,
        scene: &Scene,
        bsdf: &bsdf::BSDF,
        sampler: &mut Box<Sampler + Send + Sync>,
        arena: &Allocator,
        depth: u32,
    ) -> Spectrum {
        let flags = BxDFType::BSDF_TRANSMISSION | BxDFType::BSDF_SPECULAR;
        let (f, wi, pdf, _bsdf_type) = bsdf.sample_f(&isect.wo, &sampler.get_2d(), flags);
        let ns = &isect.shading.n;
        if pdf > 0.0 && !f.is_black() && wi.dotn(ns).abs() != 0.0 {
            let mut r = isect.spawn_ray(&wi);
            if let Some(diff) = ray.differential {
                let mut rddiff = RayDifferential::default();
                rddiff.rx_origin = isect.p + isect.dpdx;
                rddiff.ry_origin = isect.p + isect.dpdy;

                let mut eta = bsdf.eta;
                let w = -isect.wo;
                if isect.wo.dotn(ns) < 0.0 {
                    eta = 1.0 / eta;
                }

                // Compute differential reflected direction
                let dndx = isect.shading.dndu * isect.dudx + isect.dndv * isect.dvdx;
                let dndy = isect.shading.dndu * isect.dudy + isect.dndv * isect.dvdy;
                let dwodx = -diff.rx_direction - isect.wo;
                let dwody = -diff.ry_direction - isect.wo;
                let dDNdx = dwodx.dotn(ns) + isect.wo.dotn(&dndx);
                let dDNdy = dwody.dotn(ns) + isect.wo.dotn(&dndy);

                let mu = eta * w.dotn(ns) - wi.dotn(ns);
                let dmudx = (eta - (eta * eta * w.dotn(ns)) / wi.dotn(ns)) * dDNdx;
                let dmudy = (eta - (eta * eta * w.dotn(ns)) / wi.dotn(ns)) * dDNdy;

                rddiff.rx_direction = wi + eta * dwodx - Vector3f::from(mu * dndx + dDNdx * *ns);
                rddiff.ry_direction = wi + eta * dwody - Vector3f::from(mu * dndy + dDNdy * *ns);

                r.differential = Some(rddiff);
            }
            let refr = self.li(scene, &mut r, sampler, arena, depth + 1);
            f * refr * wi.dotn(ns).abs() / pdf
        } else {
            Spectrum::black()
        }
    }
}

pub fn uniform_sample_all_light(
    it: &SurfaceInteraction,
    scene: &Scene,
    sampler: &mut Box<Sampler + Send + Sync>,
    n_light_samples: &[usize],
) -> Spectrum {
    let mut L = Spectrum::black();
    for j in 0..scene.lights.len() {
        // Accumulate contribution of j_th light to L
        let light = &scene.lights[j];
        let n_samples = n_light_samples[j];
        // FIXME find a way to not copy the arrays into a vec...
        let u_light_array = sampler.get_2d_array(n_samples).map(|a| a.to_vec());
        let u_scattering_array = sampler.get_2d_array(n_samples).map(|a| a.to_vec());
        if u_scattering_array.is_none() || u_light_array.is_none() {
            // Use a single sample for illumination from light
            let u_light = sampler.get_2d();
            let u_scattering = sampler.get_2d();
            L += estimate_direct(it, &u_scattering, light, &u_light, scene, sampler);
        } else {
            let u_light_array = u_light_array.unwrap();
            let u_scattering_array = u_scattering_array.unwrap();
            let mut Ld = Spectrum::black();
            for k in 0..n_samples {
                Ld += estimate_direct(
                    it,
                    &u_scattering_array[k],
                    light,
                    &u_light_array[k],
                    scene,
                    sampler,
                );
            }
            L += Ld / n_samples as f32;
        }
    }

    L
}

pub fn uniform_sample_one_light<'a, D: Into<Option<&'a Distribution1D>>>(
    it: &SurfaceInteraction,
    scene: &Scene,
    sampler: &mut Box<Sampler + Send + Sync>,
    distrib: D,
) -> Spectrum {
    let distrib = distrib.into();
    let n_lights = scene.lights.len();
    if n_lights == 0 {
        Spectrum::black()
    } else {
        // Randomly chose a light to sample
        let s = sampler.get_1d();
        let (light_num, light_pdf) = match distrib {
            Some(distrib) => distrib.sample_discrete(s),
            None => (
                cmp::min(n_lights - 1, (s * n_lights as f32) as usize),
                1.0 / n_lights as f32,
            ),
        };

        debug!(
            "sampler.get_1d()={}, n_lights={}, light_num={}, light_pdf={}",
            s,
            n_lights,
            light_num,
            light_pdf
        );

        if light_pdf == 0.0 {
            return Spectrum::black();
        }
        let light = &scene.lights[light_num];
        let u_light = sampler.get_2d();
        let u_scattering = sampler.get_2d();
        estimate_direct(it, &u_scattering, light, &u_light, scene, sampler) / light_pdf
    }
}

pub fn estimate_direct(
    it: &SurfaceInteraction,
    u_scattering: &Point2f,
    light: &Arc<Light + Send + Sync>,
    u_light: &Point2f,
    scene: &Scene,
    _sampler: &mut Box<Sampler + Send + Sync>,
) -> Spectrum {
    let specular = false;

    let bsdf_flags = if specular {
        BxDFType::all()
    } else {
        BxDFType::all() & !BxDFType::BSDF_SPECULAR
    };
    let mut ld = Spectrum::black();
    // Sample light with multiple importance sampling
    let bsdf = it.bsdf
        .as_ref()
        .expect("There should be a BSDF set at this point!");
    let (mut li, wi, light_pdf, vis) = light.sample_li(it, u_light);
    if light_pdf > 0.0 && !li.is_black() {
        // Compute BSDF for light sample
        let f = bsdf.f(&it.wo, &wi, bsdf_flags) * wi.dotn(&it.shading.n).abs();
        let scattering_pdf = bsdf.pdf(&it.wo, &wi, bsdf_flags);
        if !f.is_black() {
            if !vis.unoccluded(scene) {
                li = Spectrum::black();
            }
            // Add light's contribution to reflected radiance
            if !li.is_black() {
                if is_delta_light(light.flags()) {
                    ld += f * li / light_pdf;
                } else {
                    let weight = power_heuristic(1, light_pdf, 1, scattering_pdf);
                    ld += f * li * weight / light_pdf;
                }
            }
        }
        // TODO compute phase function for medium interaction when supported
    }
    // Sample BSDF with multiple importance sampling
    if !is_delta_light(light.flags()) {
        let (mut f, wi, scattering_pdf, sampled_type) =
            bsdf.sample_f(&it.wo, u_scattering, bsdf_flags);
        f = f * wi.dotn(&it.shading.n).abs();
        let sampled_specular = sampled_type.contains(BxDFType::BSDF_SPECULAR);
        // TODO compute medium interaction when supported
        if !f.is_black() && scattering_pdf > 0.0 {
            // Account for light contribution along sampled direction wi
            let weight = if !sampled_specular {
                let light_pdf = light.pdf_li(it, &wi);
                if light_pdf == 0.0 {
                    return ld;
                }
                power_heuristic(1, scattering_pdf, 1, light_pdf)
            } else {
                1.0
            };

            // Find intersection and compute transmittance
            let mut ray = it.spawn_ray(&wi);
            let li = match scene.intersect(&mut ray) {
                Some(light_isect) => {
                    // Add light contribution from material sampling
                    if let Some(area_light) = light_isect.primitive.and_then(|p| p.area_light()) {
                        if area_light.id() == light.id() {
                            light_isect.le(&(-wi))
                        } else {
                            Spectrum::black()
                        }
                    } else {
                        Spectrum::black()
                    }
                }
                None => light.le(&ray),
            };
            if !li.is_black() {
                ld += f * li * weight / scattering_pdf;
            }
        }
    }

    ld
}
<|endoftext|>


<commit_before>use super::item::{Item, ItemId};
use super::context::BindgenContext;
use super::ty::TypeKind;
use super::int::IntKind;
use super::function::cursor_mangling;
use parse::{ClangItemParser, ClangSubItemParser, ParseResult, ParseError};
use clang;

#[derive(Debug)]
pub struct Var {
    /// The name of the variable.
    name: String,
    /// The mangled name of the variable.
    mangled_name: Option<String>,
    /// The type of the variable.
    ty: ItemId,
    /// TODO: support non-integer constants?
    /// The integer value of the variable.
    val: Option<i64>,
    /// Whether this variable is const.
    is_const: bool,
}

impl Var {
    pub fn new(name: String,
               mangled: Option<String>,
               ty: ItemId,
               val: Option<i64>,
               is_const: bool) -> Var {
        assert!(!name.is_empty());
        Var {
            name: name,
            mangled_name: mangled,
            ty: ty,
            val: val,
            is_const: is_const,
        }
    }

    pub fn is_const(&self) -> bool {
        self.is_const
    }

    pub fn val(&self) -> Option<i64> {
        self.val
    }

    pub fn ty(&self) -> ItemId {
        self.ty
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn mangled_name(&self) -> Option<&str> {
        self.mangled_name.as_ref().map(|n| &**n)
    }
}

impl ClangSubItemParser for Var {
    fn parse(cursor: clang::Cursor,
             context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
        use clangll::*;
        match cursor.kind() {
            CXCursor_MacroDefinition => {
                let value = match parse_int_literal_tokens(&cursor, context.translation_unit()) {
                    None => return Err(ParseError::Continue),
                    Some(v) => v,
                };

                let name = cursor.spelling();
                if name.is_empty() {
                    warn!("Empty macro name?");
                    return Err(ParseError::Continue);
                }

                if context.parsed_macro(&name) {
                    warn!("Duplicated macro definition: {}", name);
                    return Err(ParseError::Continue);
                }
                context.note_parsed_macro(name.clone());

                let ty = if value < 0 {
                    Item::builtin_type(TypeKind::Int(IntKind::Int), true, context)
                } else if value.abs() > u32::max_value() as i64  {
                    Item::builtin_type(TypeKind::Int(IntKind::ULongLong), true, context)
                } else {
                    Item::builtin_type(TypeKind::Int(IntKind::UInt), true, context)
                };

                Ok(ParseResult::New(Var::new(name, None, ty, Some(value), true), Some(cursor)))
            }
            CXCursor_VarDecl => {
                let name = cursor.spelling();
                if name.is_empty() {
                    warn!("Empty constant name?");
                    return Err(ParseError::Continue);
                }

                let ty = cursor.cur_type();

                // XXX this is redundant, remove!
                let is_const = ty.is_const();

                let ty = Item::from_ty(&ty, Some(cursor), None, context)
                            .expect("Unable to resolve constant type?");

                let mut value = None;

                // Note: Ty might not be totally resolved yet, see
                // tests/headers/inner_const.hpp
                //
                // That's fine because in that case we know it's not a literal.
                if context.safe_resolve_type(ty).map_or(false, |t| t.is_integer(context)) {
                    // Try to parse a literal token value
                    cursor.visit(|c, _| {
                        if c.kind() == CXCursor_IntegerLiteral {
                            value = parse_int_literal_tokens(&c, context.translation_unit());
                        }
                        CXChildVisit_Continue
                    });
                }

                let mangling = cursor_mangling(&cursor);

                let var = Var::new(name, mangling, ty, value, is_const);
                Ok(ParseResult::New(var, Some(cursor)))

            }
            _ => {
                /* TODO */
                Err(ParseError::Continue)
            }
        }
    }
}

/// Try and parse the immediately found tokens from an unit (if any) to integers
fn parse_int_literal_tokens(cursor: &clang::Cursor,
                            unit: &clang::TranslationUnit) -> Option<i64> {
    use clangll::{CXToken_Literal, CXToken_Punctuation};

    let mut lit = String::new();
    let tokens = match unit.tokens(cursor) {
        None => return None,
        Some(tokens) => tokens,
    };

    for token in tokens {
        match token.kind {
            CXToken_Punctuation if token.spelling == "-" => {
                // If there's ever any punctuation, we only need to worry about
                // unary minus '-' (for now)
                lit.push_str(&token.spelling);
            },
            CXToken_Literal => {
                lit.push_str(&token.spelling);
                break
            },
            _ => (),
        }
    }

    // TODO: try to preserve hex literals?
    if lit.starts_with("0x") {
        i64::from_str_radix(&lit[2..], 16).ok()
    } else {
        lit.parse().ok()
    }
}
<commit_msg>Try to read integer literal from expr<commit_after>use super::item::{Item, ItemId};
use super::context::BindgenContext;
use super::ty::TypeKind;
use super::int::IntKind;
use super::function::cursor_mangling;
use parse::{ClangItemParser, ClangSubItemParser, ParseResult, ParseError};
use clang;

#[derive(Debug)]
pub struct Var {
    /// The name of the variable.
    name: String,
    /// The mangled name of the variable.
    mangled_name: Option<String>,
    /// The type of the variable.
    ty: ItemId,
    /// TODO: support non-integer constants?
    /// The integer value of the variable.
    val: Option<i64>,
    /// Whether this variable is const.
    is_const: bool,
}

impl Var {
    pub fn new(name: String,
               mangled: Option<String>,
               ty: ItemId,
               val: Option<i64>,
               is_const: bool) -> Var {
        assert!(!name.is_empty());
        Var {
            name: name,
            mangled_name: mangled,
            ty: ty,
            val: val,
            is_const: is_const,
        }
    }

    pub fn is_const(&self) -> bool {
        self.is_const
    }

    pub fn val(&self) -> Option<i64> {
        self.val
    }

    pub fn ty(&self) -> ItemId {
        self.ty
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn mangled_name(&self) -> Option<&str> {
        self.mangled_name.as_ref().map(|n| &**n)
    }
}

impl ClangSubItemParser for Var {
    fn parse(cursor: clang::Cursor,
             context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> {
        use clangll::*;
        match cursor.kind() {
            CXCursor_MacroDefinition => {
                let value = match parse_int_literal_tokens(&cursor, context.translation_unit()) {
                    None => return Err(ParseError::Continue),
                    Some(v) => v,
                };

                let name = cursor.spelling();
                if name.is_empty() {
                    warn!("Empty macro name?");
                    return Err(ParseError::Continue);
                }

                if context.parsed_macro(&name) {
                    warn!("Duplicated macro definition: {}", name);
                    return Err(ParseError::Continue);
                }
                context.note_parsed_macro(name.clone());

                let ty = if value < 0 {
                    Item::builtin_type(TypeKind::Int(IntKind::Int), true, context)
                } else if value.abs() > u32::max_value() as i64  {
                    Item::builtin_type(TypeKind::Int(IntKind::ULongLong), true, context)
                } else {
                    Item::builtin_type(TypeKind::Int(IntKind::UInt), true, context)
                };

                Ok(ParseResult::New(Var::new(name, None, ty, Some(value), true), Some(cursor)))
            }
            CXCursor_VarDecl => {
                let name = cursor.spelling();
                if name.is_empty() {
                    warn!("Empty constant name?");
                    return Err(ParseError::Continue);
                }

                let ty = cursor.cur_type();

                // XXX this is redundant, remove!
                let is_const = ty.is_const();

                let ty = Item::from_ty(&ty, Some(cursor), None, context)
                            .expect("Unable to resolve constant type?");

                // Note: Ty might not be totally resolved yet, see
                // tests/headers/inner_const.hpp
                //
                // That's fine because in that case we know it's not a literal.
                let value = context.safe_resolve_type(ty).map_or(None, |t| {
                    if t.is_integer(context) {
                        get_integer_literal_from_cursor(&cursor, context.translation_unit())
                    } else {
                        None
                    }
                });

                let mangling = cursor_mangling(&cursor);

                let var = Var::new(name, mangling, ty, value, is_const);
                Ok(ParseResult::New(var, Some(cursor)))

            }
            _ => {
                /* TODO */
                Err(ParseError::Continue)
            }
        }
    }
}

/// Try and parse the immediately found tokens from an unit (if any) to integers
fn parse_int_literal_tokens(cursor: &clang::Cursor,
                            unit: &clang::TranslationUnit) -> Option<i64> {
    use clangll::{CXToken_Literal, CXToken_Punctuation};

    let mut lit = String::new();
    let tokens = match unit.tokens(cursor) {
        None => return None,
        Some(tokens) => tokens,
    };

    for token in tokens {
        match token.kind {
            CXToken_Punctuation if token.spelling == "-" => {
                // If there's ever any punctuation, we only need to worry about
                // unary minus '-' (for now)
                lit.push_str(&token.spelling);
            },
            CXToken_Literal => {
                lit.push_str(&token.spelling);
                break
            },
            _ => (),
        }
    }

    // TODO: try to preserve hex literals?
    if lit.starts_with("0x") {
        i64::from_str_radix(&lit[2..], 16).ok()
    } else {
        lit.parse().ok()
    }
}

fn get_integer_literal_from_cursor(cursor: &clang::Cursor,
                                   unit: &clang::TranslationUnit) -> Option<i64> {
    use clangll::*;
    let mut value = None;
    cursor.visit(|c, _| {
        match c.kind() {
            CXCursor_IntegerLiteral => {
                value = parse_int_literal_tokens(&c, unit);
            }
            CXCursor_UnexposedExpr => {
                value = get_integer_literal_from_cursor(&c, unit);
            }
            _ => ()
        }
        if value.is_some() {
            CXChildVisit_Break
        } else {
            CXChildVisit_Continue
        }
    });
    value
}
<|endoftext|>


<commit_before>use data::{Value, List, Function, Scope, RuntimeError};
use list::ListIter;
use scope::LocalScope;

#[derive(Debug, PartialEq)]
pub struct Lambda
{
    args: Vec<String>,
    code: List,
    //env: &'a mut Scope,
}

impl Lambda
{
    pub fn new(args: Vec<String>, code: List) -> Lambda
    {
        Lambda{ args: args, code: code }
    }
}

impl Lambda
{
    fn call_impl(&self, mut vals: ListIter, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        let mut local = LocalScope::new(env);
        for name in self.args.iter()
        {
            local.decl(&name, vals.next().unwrap_or(Value::Nil));
        }
        self.code.eval_to_value(&mut local)
    }
}

impl Function for Lambda
{
    fn call(&self, args: &List, env: &mut Scope, do_eval: bool) -> Result<Value, RuntimeError>
    {
        if do_eval
        {
            let vals = try!(args.eval(env));
            self.call_impl(vals.iter(), env)
        }
        else
        {
            self.call_impl(args.iter(), env)
        }
    }
}
<commit_msg>fail lambda calls with missing args (instead of setting them Nil)<commit_after>use data::{Value, List, Function, Scope, RuntimeError};
use list::ListIter;
use scope::LocalScope;

#[derive(Debug, PartialEq)]
pub struct Lambda
{
    args: Vec<String>,
    code: List,
    //env: &'a mut Scope,
}

impl Lambda
{
    pub fn new(args: Vec<String>, code: List) -> Lambda
    {
        Lambda{ args: args, code: code }
    }

    fn call_impl(&self, mut vals: ListIter, env: &mut Scope) -> Result<Value, RuntimeError>
    {
        let mut local = LocalScope::new(env);
        for (i, name) in self.args.iter().enumerate()
        {
            local.decl(&name, match vals.next() {
                Some(val) => val,
                None => return Err(RuntimeError::InvalidArgNum(self.args.len() as u32, i as u32)),
            });
        }
        self.code.eval_to_value(&mut local)
    }
}

impl Function for Lambda
{
    fn call(&self, args: &List, env: &mut Scope, do_eval: bool) -> Result<Value, RuntimeError>
    {
        if do_eval
        {
            let vals = try!(args.eval(env));
            self.call_impl(vals.iter(), env)
        }
        else
        {
            self.call_impl(args.iter(), env)
        }
    }
}
<|endoftext|>


<commit_before>use command::JudgingCommand;
use errors::JudgeResult;
use judging::{JudgingOutput, MillisRoundedUp};
use testsuite::SimpleCase;
use util;

use term::color;

use std::{fmt, thread};
use std::io::{self, Write};
use std::process::ExitStatus;
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};

/// Tests for `case` and `solver` and returns one `SimpleOutput`.
pub fn judge(case: SimpleCase, solver: Arc<JudgingCommand>) -> JudgeResult<SimpleOutput> {
    let (tx, rx) = mpsc::channel();
    let case = Arc::new(case);
    {
        let (case, solver) = (case.clone(), solver.clone());
        thread::spawn(move || {
            let _ = tx.send(run(&case, &solver));
        });
    }
    Ok(if let (input, expected, Some(timelimit)) = case.values() {
        rx.recv_timeout(timelimit + Duration::from_millis(50))
            .unwrap_or_else(|_| Ok(SimpleOutput::Tle(timelimit, input, expected)))
    } else {
        rx.recv()?
    }?)
}

fn run(case: &SimpleCase, solver: &JudgingCommand) -> io::Result<SimpleOutput> {
    let (input, expected, timelimit) = case.values();
    let mut solver = solver.spawn_piped()?;
    let start = Instant::now();
    solver.stdin.as_mut().unwrap().write_all(input.as_bytes())?;

    let status = solver.wait()?;
    let t = start.elapsed();
    let stdout = Arc::new(util::string_from_read(solver.stdout.unwrap())?);
    let stderr = Arc::new(util::string_from_read(solver.stderr.unwrap())?);

    // `expected` is empty IFF omitted.
    if timelimit.is_some() && t > timelimit.unwrap() {
        Ok(SimpleOutput::Tle(timelimit.unwrap(), input, expected))
    } else if status.success() && (expected.is_empty() || expected == stdout) {
        Ok(SimpleOutput::Ac(t, input, stdout, stderr))
    } else if status.success() {
        Ok(SimpleOutput::Wa(t, input, expected, stdout, stderr))
    } else {
        Ok(SimpleOutput::Re(t, input, expected, stdout, stderr, status))
    }
}

/// Test result.
pub enum SimpleOutput {
    // Each string may be empty.
    // (<elapsed>, <input>, <stdout>, <stderr>)
    Ac(Duration, Arc<String>, Arc<String>, Arc<String>),
    // (<timelimit>, <input>, <expected>)
    Tle(Duration, Arc<String>, Arc<String>),
    // (<elapsed>, <input>, <expected>, <stdout>, <stderr>)
    Wa(Duration, Arc<String>, Arc<String>, Arc<String>, Arc<String>),
    // (<elapsed>, <input>, <expected>, <stdout>, <stderr>, <status>)
    Re(
        Duration,
        Arc<String>,
        Arc<String>,
        Arc<String>,
        Arc<String>,
        ExitStatus,
    ),
}

impl fmt::Display for SimpleOutput {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SimpleOutput::Ac(t, ..) => write!(f, "AC ({}ms)", t.millis_rounded_up()),
            SimpleOutput::Tle(t, ..) => write!(f, "TLE ({}ms)", t.millis_rounded_up()),
            SimpleOutput::Wa(t, ..) => write!(f, "WA ({}ms)", t.millis_rounded_up()),
            SimpleOutput::Re(t, .., status) => {
                write!(f, "RE ({}, {}ms)", status, t.millis_rounded_up())
            }
        }
    }
}

impl JudgingOutput for SimpleOutput {
    fn failure(&self) -> bool {
        match *self {
            SimpleOutput::Ac(..) => false,
            _ => true,
        }
    }

    fn color(&self) -> u32 {
        match *self {
            SimpleOutput::Ac(..) => color::GREEN,
            SimpleOutput::Tle(..) => color::RED,
            SimpleOutput::Wa(..) => color::YELLOW,
            SimpleOutput::Re(..) => color::YELLOW,
        }
    }

    fn eprint_details(&self) {
        const THRESHOLD_TO_OMIT: usize = 1024;

        fn eprint_size(num_bytes: usize) {
            if num_bytes > 10 * 1024 * 1024 {
                let mb = num_bytes / (1024 * 1024);
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}MB)", mb);
            } else if num_bytes > 10 * 1024 {
                let kb = num_bytes / 1024;
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}KB)", kb);
            } else {
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}B)", num_bytes);
            }
        }

        fn eprint_section(head: &'static str, content: &str) {
            let num_bytes = content.as_bytes().len();
            eprintln_bold!(Some(color::MAGENTA), "{}:", head);
            if num_bytes == 0 {
                eprintln_bold!(Some(color::YELLOW), "EMPTY");
            } else if num_bytes > THRESHOLD_TO_OMIT {
                eprint_size(num_bytes);
            } else {
                util::eprintln_trimming_trailing_newline(content);
            }
        }

        fn eprint_section_unless_empty(head: &'static str, content: &str) {
            let num_bytes = content.as_bytes().len();
            if num_bytes > THRESHOLD_TO_OMIT {
                eprint_size(num_bytes);
            } else if num_bytes > 0 {
                eprintln_bold!(Some(color::MAGENTA), "{}:", head);
                util::eprintln_trimming_trailing_newline(content);
            }
        }

        match *self {
            SimpleOutput::Ac(_, ref input, ref stdout, ref stderr) => {
                eprint_section("input", input);
                eprint_section("stdout", stdout);
                eprint_section_unless_empty("stderr", stderr);
            }
            SimpleOutput::Tle(_, ref input, ref expected) => {
                eprint_section("input", input);
                eprint_section_unless_empty("expected", expected);
            }
            SimpleOutput::Wa(_, ref input, ref expected, ref stdout, ref stderr) => {
                eprint_section("input", input);
                eprint_section("expected", expected);
                eprint_section("stdout", stdout);
                eprint_section_unless_empty("stderr", stderr);
            }
            SimpleOutput::Re(_, ref input, ref expected, ref stdout, ref stderr, _) => {
                eprint_section("input", input);
                eprint_section_unless_empty("expected", expected);
                eprint_section_unless_empty("stdout", stdout);
                eprint_section("stderr", stderr);
            }
        }
    }
}
<commit_msg>Change the names of test results<commit_after>use command::JudgingCommand;
use errors::JudgeResult;
use judging::{JudgingOutput, MillisRoundedUp};
use testsuite::SimpleCase;
use util;

use term::color;

use std::{fmt, thread};
use std::io::{self, Write};
use std::process::ExitStatus;
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};

/// Tests for `case` and `solver` and returns one `SimpleOutput`.
pub fn judge(case: SimpleCase, solver: Arc<JudgingCommand>) -> JudgeResult<SimpleOutput> {
    let (tx, rx) = mpsc::channel();
    let case = Arc::new(case);
    {
        let (case, solver) = (case.clone(), solver.clone());
        thread::spawn(move || {
            let _ = tx.send(run(&case, &solver));
        });
    }
    Ok(if let (input, expected, Some(timelimit)) = case.values() {
        rx.recv_timeout(timelimit + Duration::from_millis(50))
            .unwrap_or_else(|_| Ok(SimpleOutput::Tle(timelimit, input, expected)))
    } else {
        rx.recv()?
    }?)
}

fn run(case: &SimpleCase, solver: &JudgingCommand) -> io::Result<SimpleOutput> {
    let (input, expected, timelimit) = case.values();
    let mut solver = solver.spawn_piped()?;
    let start = Instant::now();
    solver.stdin.as_mut().unwrap().write_all(input.as_bytes())?;

    let status = solver.wait()?;
    let t = start.elapsed();
    let stdout = Arc::new(util::string_from_read(solver.stdout.unwrap())?);
    let stderr = Arc::new(util::string_from_read(solver.stderr.unwrap())?);

    // `expected` is empty IFF omitted.
    if timelimit.is_some() && t > timelimit.unwrap() {
        Ok(SimpleOutput::Tle(timelimit.unwrap(), input, expected))
    } else if status.success() && (expected.is_empty() || expected == stdout) {
        Ok(SimpleOutput::Ac(t, input, stdout, stderr))
    } else if status.success() {
        Ok(SimpleOutput::Wa(t, input, expected, stdout, stderr))
    } else {
        Ok(SimpleOutput::Re(t, input, expected, stdout, stderr, status))
    }
}

/// Test result.
pub enum SimpleOutput {
    // Each string may be empty.
    // (<elapsed>, <input>, <stdout>, <stderr>)
    Ac(Duration, Arc<String>, Arc<String>, Arc<String>),
    // (<timelimit>, <input>, <expected>)
    Tle(Duration, Arc<String>, Arc<String>),
    // (<elapsed>, <input>, <expected>, <stdout>, <stderr>)
    Wa(Duration, Arc<String>, Arc<String>, Arc<String>, Arc<String>),
    // (<elapsed>, <input>, <expected>, <stdout>, <stderr>, <status>)
    Re(
        Duration,
        Arc<String>,
        Arc<String>,
        Arc<String>,
        Arc<String>,
        ExitStatus,
    ),
}

impl fmt::Display for SimpleOutput {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SimpleOutput::Ac(t, ..) => write!(f, "Accepted ({}ms)", t.millis_rounded_up()),
            SimpleOutput::Tle(t, ..) => {
                write!(f, "Time Limit Exceeded ({}ms)", t.millis_rounded_up())
            }
            SimpleOutput::Wa(t, ..) => write!(f, "Wrong Answer ({}ms)", t.millis_rounded_up()),
            SimpleOutput::Re(t, .., status) => {
                write!(f, "Runtime Error ({}, {}ms)", status, t.millis_rounded_up())
            }
        }
    }
}

impl JudgingOutput for SimpleOutput {
    fn failure(&self) -> bool {
        match *self {
            SimpleOutput::Ac(..) => false,
            _ => true,
        }
    }

    fn color(&self) -> u32 {
        match *self {
            SimpleOutput::Ac(..) => color::GREEN,
            SimpleOutput::Tle(..) => color::RED,
            SimpleOutput::Wa(..) => color::YELLOW,
            SimpleOutput::Re(..) => color::YELLOW,
        }
    }

    fn eprint_details(&self) {
        const THRESHOLD_TO_OMIT: usize = 1024;

        fn eprint_size(num_bytes: usize) {
            if num_bytes > 10 * 1024 * 1024 {
                let mb = num_bytes / (1024 * 1024);
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}MB)", mb);
            } else if num_bytes > 10 * 1024 {
                let kb = num_bytes / 1024;
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}KB)", kb);
            } else {
                eprintln_bold!(Some(color::YELLOW), "OMITTED ({}B)", num_bytes);
            }
        }

        fn eprint_section(head: &'static str, content: &str) {
            let num_bytes = content.as_bytes().len();
            eprintln_bold!(Some(color::MAGENTA), "{}:", head);
            if num_bytes == 0 {
                eprintln_bold!(Some(color::YELLOW), "EMPTY");
            } else if num_bytes > THRESHOLD_TO_OMIT {
                eprint_size(num_bytes);
            } else {
                util::eprintln_trimming_trailing_newline(content);
            }
        }

        fn eprint_section_unless_empty(head: &'static str, content: &str) {
            let num_bytes = content.as_bytes().len();
            if num_bytes > THRESHOLD_TO_OMIT {
                eprint_size(num_bytes);
            } else if num_bytes > 0 {
                eprintln_bold!(Some(color::MAGENTA), "{}:", head);
                util::eprintln_trimming_trailing_newline(content);
            }
        }

        match *self {
            SimpleOutput::Ac(_, ref input, ref stdout, ref stderr) => {
                eprint_section("input", input);
                eprint_section("stdout", stdout);
                eprint_section_unless_empty("stderr", stderr);
            }
            SimpleOutput::Tle(_, ref input, ref expected) => {
                eprint_section("input", input);
                eprint_section_unless_empty("expected", expected);
            }
            SimpleOutput::Wa(_, ref input, ref expected, ref stdout, ref stderr) => {
                eprint_section("input", input);
                eprint_section("expected", expected);
                eprint_section("stdout", stdout);
                eprint_section_unless_empty("stderr", stderr);
            }
            SimpleOutput::Re(_, ref input, ref expected, ref stdout, ref stderr, _) => {
                eprint_section("input", input);
                eprint_section_unless_empty("expected", expected);
                eprint_section_unless_empty("stdout", stdout);
                eprint_section("stderr", stderr);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::LinkedList;

use common;
use implicit;
use explicit;
use typed;

use implicit::Expr;
use common::{Id, Result};
use refined::{Base, T};
pub use explicit::Metavar;

// Qbc (bounds checking)
// X: 0, *, len *
// ν < X
// ν <= X
// ν = X
// ν >= X
// ν > X

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum C {
    WellFormed(Box<Type>),
    Subtype(Box<Type>, Box<Type>),
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Liquid {
    E(implicit::Expr),
    K(Metavar, Box<LinkedList<Expr>>), // list of pending substitutions
}

pub type Type = T<Liquid>;

pub type Constraint = ((HashSet<Id>, LinkedList<Expr>), C); // Boolean valued expressions & their environments

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Env {
    shape: HashMap<Id, explicit::Type>,
    refined_env: HashMap<Id, Type>,
    path_constraints: LinkedList<Expr>,
}

impl Env {
    fn new(shape: &HashMap<Id, explicit::Type>) -> Env {
        Env {
            shape: shape.clone(),
            refined_env: HashMap::new(),
            path_constraints: LinkedList::new(),
        }
    }

    fn get(&self, s: &Id) -> Type {
        match self.refined_env.get(s) {
            Some(ty) => ty.clone(),
            None => panic!("env.get('{}' missing ({:?})", s, self.in_scope()),
        }
    }

    fn insert(&mut self, s: &Id, ty: &Type) {
        self.refined_env.insert(s.clone(), ty.clone());
    }

    fn add_constraint(&mut self, e: &Expr) {
        self.path_constraints.push_back(e.clone())
    }

    fn in_scope(&self) -> HashSet<Id> {
        let keys: HashSet<_> = self.refined_env.keys().cloned().collect();
        return keys
    }

    fn snapshot(&self) -> (HashSet<Id>, LinkedList<Expr>) {
        (self.in_scope(), self.path_constraints.clone())
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct KEnv {
    shape: HashMap<Id, explicit::Type>,
    env_id: String,
    next_id: i32,
}

fn hm_shape(env: &HashMap<Id, explicit::Type>, expr: &Expr) -> explicit::Type {
    use implicit::Expr::*;
    use explicit::Type::*;

    match *expr {
        Var(ref id) => env.get(id).unwrap().clone(),
        Const(common::Const::Int(_)) => TInt,
        Const(common::Const::Bool(_)) => TBool,
        Op2(op, _, _) => explicit::opty(op),
        Fun(ref id, ref e) => TFun(box env.get(id).unwrap().clone(), box hm_shape(env, e)),
        App(ref e1, _) => {
            if let TFun(_, e2) = hm_shape(env, e1) {
                *e2
            } else {
                panic!("expected TFun, not {:?}", expr);
            }
        }
        If(_, ref e2, _) => hm_shape(env, e2),
        Let(ref id, ref e1, ref e2) => hm_shape(env, e2),
        Fix(ref id, ref e) => hm_shape(env, e),
        MkArray(ref sz, ref n) => TIntArray,
        GetArray(ref id, ref idx) => TInt,
        SetArray(ref id, ref idx, ref v) => TIntArray,
        Star => panic!("star found when it shouldn't be"),
        V => panic!("v found when it shouldn't be"),
    }
}

impl KEnv {
    fn new(shape: &HashMap<Id, explicit::Type>) -> KEnv {
        KEnv {
            shape: shape.clone(),
            env_id: String::from("κ"), // ν
            next_id: 0,
        }
    }

    fn fresh_ty(&mut self, env: &Env, ty: &explicit::Type) -> Type {
        let id = self.next_id;
        self.next_id += 1;

        let base = match *ty {
            explicit::Type::TInt => Base::Int,
            explicit::Type::TBool => Base::Bool,
            _ => panic!("FIXME: handle {:?}", ty),
        };
        let k = Liquid::K((id, self.env_id.clone()), box LinkedList::new());
        T::Ref(env.in_scope(), base, box k)
    }

    fn fresh(&mut self, env: &Env, expr: &Expr) -> Type {
        if let &Expr::Fun(ref id, ref e) = expr {
            let t1 = &self.shape.get(id).unwrap().clone();
            let fx = self.fresh_ty(env, t1);
            let f = self.fresh(env, e);
            T::Fun(id.clone(), box fx, box f)
        } else {
            let ty = hm_shape(&env.shape, expr);
            self.fresh_ty(env, &ty)
        }
    }
}

fn ty<'a>(k_env: &mut KEnv, env: &Env, c: &common::Const) -> Type {
    use common::Op2;
    use common::Const::*;
    use self::Liquid::E;

    let base = match *c {
        Int(_) => Base::Int,
        Bool(_) => Base::Bool,
    };

    println!("ty({:?})", base);

    // {ν : int | ν = 3 }
    let eq = E(Expr::Op2(Op2::Eq, box Expr::V, box Expr::Const(*c)));
    T::Ref(HashSet::new(), base, box eq)
}

fn base(ty: &Type) -> Option<Base> {
    match *ty {
        T::Ref(_, b, _) => Some(b),
        _ => None,
    }
}

pub fn cons<'a>(k_env: &mut KEnv, env: &Env, expr: &Expr) -> (Type, LinkedList<Constraint>) {
    use implicit::Expr::*;
    use common::Op2::Eq;

    match *expr {
        Var(ref id) => {
            let ty: Type = if let Some(b) = base(&env.get(id)) {
                let eq = Op2(Eq, box V, box Var(id.clone()));
                T::Ref(env.in_scope(), b, box Liquid::E(eq))
            } else {
                env.get(id)
            };
            (ty, LinkedList::new())
        }
        Const(ref c) => {
            (ty(k_env, &env, c), LinkedList::new())
        }
        Op2(op, ref e1, ref e2) => {
            let (f1, mut c1) = cons(k_env, env, e1);
            let (f2, mut c2) = cons(k_env, env, e2);
            c1.append(&mut c2);

            let ty = explicit::opty(op);
            let base = match ty {
                explicit::Type::TInt => Base::Int,
                explicit::Type::TBool => Base::Bool,
                _ => panic!("FIXME: handle {:?}", ty),
            };

            let eq = Op2(Eq, box V, box expr.clone());
            let f = T::Ref(env.in_scope(), base, box Liquid::E(eq));
            println!("!!f:\t{:?}", f);

            (f, c1)
        }
        If(ref e1, ref e2, ref e3) => {
            let mut env_t = env.clone();
            let mut env_f = env.clone();
            env_t.add_constraint(&e1.clone());
            env_f.add_constraint(&App(box Var(String::from("not")), e1.clone()));

            let f = k_env.fresh(&env, expr);
            // type of e1 has already been verified to be a bool by HM
            let (_, mut c1) = cons(k_env, &env, e1);
            let (f2, mut c2) = cons(k_env, &env_t, e2);
            let (f3, mut c3) = cons(k_env, &env_f, e3);
            c1.append(&mut c2);
            c1.append(&mut c3);
            // Γ ⊢ (f)
            c1.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,e1 ⊢ (f2 <: f)
            c1.push_back((env_t.snapshot(), C::Subtype(box f2.clone(), box f.clone())));
            // Γ,¬e1 ⊢ (f3 <: f)
            c1.push_back((env_f.snapshot(), C::Subtype(box f3.clone(), box f.clone())));

            (f, c1)
        }
        Fun(ref x, ref e) => {
            let mut env = env.clone();
            let fx = k_env.fresh(&env, &Var(x.clone()));
            env.insert(x, &fx);
            let f = k_env.fresh(&env, e);
            let (fe, mut c) = cons(k_env, &env, e);
            // Γ ⊢ (x:fx → f)
            c.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,x:fx ⊢ (fe <: f)
            c.push_back((env.snapshot(), C::Subtype(box fe.clone(), box f.clone())));

            (f, c)
        }
        Fix(ref x, ref e) => {
            // const w/ ∀α.(α→α)→α
            let mut env = env.clone();
            let fx = k_env.fresh(&env, e);
            env.insert(x, &fx);

            // FIXME
            cons(k_env, &env, e)
        }
        Let(ref id, ref e1, ref e2) => {
            let mut env = env.clone();

            let f = k_env.fresh(&env, expr);
            let (f1, mut c1) = cons(k_env, &env, e1);
            env.insert(id, &f1);
            let (f2, mut c2) = cons(k_env, &env, e2);
            c1.append(&mut c2);
            // Γ ⊢ (f)
            c1.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,x:f1 ⊢ (f2 <: f)
            c1.push_back((env.snapshot(), C::Subtype(box f2.clone(), box f.clone())));

            (f, c1)
        }
        _ => {
            println!("unhandled {:?}", expr);
            (T::Ref(env.in_scope(), Base::Bool, box Liquid::E(Const(common::Const::Bool(true)))), LinkedList::new())
        }
    }
}

pub fn infer(expr: &Expr, env: &HashMap<Id, explicit::Type>) -> Result<Expr> {
    let mut k_env = KEnv::new(env);
    let (f, c) = cons(&mut k_env, &Env::new(env), expr);
    println!("CONS:\n");
    println!("f\t{:?}", f);
    println!("c\t{:?}", c);

    // TODO:
    // let a = Solve(Split(c), λκ.Inst(Γ, e, Q)) in
    // a(f)

    Ok(Expr::Const(common::Const::Bool(false)))
}
<commit_msg>liquid: more work on constraint generation -- close<commit_after>use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::LinkedList;

use common;
use implicit;
use explicit;
use typed;

use implicit::Expr;
use common::{Id, Result};
use refined::{Base, T};
pub use explicit::Metavar;

// Qbc (bounds checking)
// X: 0, *, len *
// ν < X
// ν <= X
// ν = X
// ν >= X
// ν > X

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum C {
    WellFormed(Box<Type>),
    Subtype(Box<Type>, Box<Type>),
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Liquid {
    E(implicit::Expr),
    K(Metavar, Box<LinkedList<Expr>>), // list of pending substitutions
}

pub type Type = T<Liquid>;

pub type Constraint = ((HashSet<Id>, LinkedList<Expr>), C); // Boolean valued expressions & their environments

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Env {
    shape: HashMap<Id, explicit::Type>,
    refined_env: HashMap<Id, Type>,
    path_constraints: LinkedList<Expr>,
}

impl Env {
    fn new(shape: &HashMap<Id, explicit::Type>) -> Env {
        Env {
            shape: shape.clone(),
            refined_env: HashMap::new(),
            path_constraints: LinkedList::new(),
        }
    }

    fn get(&self, s: &Id) -> Type {
        match self.refined_env.get(s) {
            Some(ty) => ty.clone(),
            None => panic!("env.get('{}' missing ({:?})", s, self.in_scope()),
        }
    }

    fn insert(&mut self, s: &Id, ty: &Type) {
        self.refined_env.insert(s.clone(), ty.clone());
    }

    fn add_constraint(&mut self, e: &Expr) {
        self.path_constraints.push_back(e.clone())
    }

    fn in_scope(&self) -> HashSet<Id> {
        let keys: HashSet<_> = self.refined_env.keys().cloned().collect();
        return keys
    }

    fn snapshot(&self) -> (HashSet<Id>, LinkedList<Expr>) {
        (self.in_scope(), self.path_constraints.clone())
    }
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct KEnv {
    shape: HashMap<Id, explicit::Type>,
    env_id: String,
    next_id: i32,
}

fn hm_shape(env: &HashMap<Id, explicit::Type>, expr: &Expr) -> explicit::Type {
    use implicit::Expr::*;
    use explicit::Type::*;

    match *expr {
        Var(ref id) => env.get(id).unwrap().clone(),
        Const(common::Const::Int(_)) => TInt,
        Const(common::Const::Bool(_)) => TBool,
        Op2(op, _, _) => explicit::opty(op),
        Fun(ref id, ref e) => TFun(box env.get(id).unwrap().clone(), box hm_shape(env, e)),
        App(ref e1, _) => {
            if let TFun(_, e2) = hm_shape(env, e1) {
                *e2
            } else {
                panic!("expected TFun, not {:?}", expr);
            }
        }
        If(_, ref e2, _) => hm_shape(env, e2),
        Let(ref id, ref e1, ref e2) => hm_shape(env, e2),
        Fix(ref id, ref e) => hm_shape(env, e),
        MkArray(ref sz, ref n) => TIntArray,
        GetArray(ref id, ref idx) => TInt,
        SetArray(ref id, ref idx, ref v) => TIntArray,
        Star => panic!("star found when it shouldn't be"),
        V => panic!("v found when it shouldn't be"),
    }
}

impl KEnv {
    fn new(shape: &HashMap<Id, explicit::Type>) -> KEnv {
        KEnv {
            shape: shape.clone(),
            env_id: String::from("κ"), // ν
            next_id: 0,
        }
    }

    fn fresh_ty(&mut self, env: &Env, ty: &explicit::Type) -> Type {
        let id = self.next_id;
        self.next_id += 1;

        let base = match *ty {
            explicit::Type::TInt => Base::Int,
            explicit::Type::TBool => Base::Bool,
            _ => panic!("FIXME: handle {:?}", ty),
        };
        let k = Liquid::K((id, self.env_id.clone()), box LinkedList::new());
        T::Ref(env.in_scope(), base, box k)
    }

    fn fresh(&mut self, env: &Env, expr: &Expr) -> Type {
        if let &Expr::Fun(ref id, ref e) = expr {
            let t1 = &self.shape.get(id).unwrap().clone();
            let fx = self.fresh_ty(env, t1);
            let f = self.fresh(env, e);
            T::Fun(id.clone(), box fx, box f)
        } else {
            let ty = hm_shape(&env.shape, expr);
            self.fresh_ty(env, &ty)
        }
    }
}

fn ty<'a>(k_env: &mut KEnv, env: &Env, c: &common::Const) -> Type {
    use common::Op2;
    use common::Const::*;
    use self::Liquid::E;

    let base = match *c {
        Int(_) => Base::Int,
        Bool(_) => Base::Bool,
    };

    println!("ty({:?})", base);

    // {ν : int | ν = 3 }
    let eq = E(Expr::Op2(Op2::Eq, box Expr::V, box Expr::Const(*c)));
    T::Ref(HashSet::new(), base, box eq)
}

fn base(ty: &Type) -> Option<Base> {
    match *ty {
        T::Ref(_, b, _) => Some(b),
        _ => None,
    }
}

fn subst(id: &Id, expr: &Expr, ty: &Type) -> Type {
    println!("TODO: subst");
    ty.clone()
}

pub fn cons<'a>(k_env: &mut KEnv, env: &Env, expr: &Expr) -> (Type, LinkedList<Constraint>) {
    use implicit::Expr::*;
    use common::Op2::Eq;

    match *expr {
        Var(ref id) => {
            let ty: Type = if let Some(b) = base(&env.get(id)) {
                println!("{} is base ({:?})", id, b);
                let eq = Op2(Eq, box V, box Var(id.clone()));
                T::Ref(env.in_scope(), b, box Liquid::E(eq))
            } else {
                println!("{} not base -- using just env ({:?})", id, env.get(id));
                env.get(id)
            };
            (ty, LinkedList::new())
        }
        Const(ref c) => {
            (ty(k_env, &env, c), LinkedList::new())
        }
        Op2(op, ref e1, ref e2) => {
            let (f1, mut c1) = cons(k_env, env, e1);
            let (f2, mut c2) = cons(k_env, env, e2);
            c1.append(&mut c2);

            let ty = explicit::opty(op);
            let base = match ty {
                explicit::Type::TInt => Base::Int,
                explicit::Type::TBool => Base::Bool,
                _ => panic!("FIXME: handle {:?}", ty),
            };

            let eq = Op2(Eq, box V, box expr.clone());
            let f = T::Ref(env.in_scope(), base, box Liquid::E(eq));

            (f, c1)
        }
        If(ref e1, ref e2, ref e3) => {
            let mut env_t = env.clone();
            let mut env_f = env.clone();
            env_t.add_constraint(&e1.clone());
            env_f.add_constraint(&App(box Var(String::from("not")), e1.clone()));

            let f = k_env.fresh(&env, expr);
            // type of e1 has already been verified to be a bool by HM
            let (_, mut c1) = cons(k_env, &env, e1);
            let (f2, mut c2) = cons(k_env, &env_t, e2);
            let (f3, mut c3) = cons(k_env, &env_f, e3);
            c1.append(&mut c2);
            c1.append(&mut c3);
            // Γ ⊢ (f)
            c1.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,e1 ⊢ (f2 <: f)
            c1.push_back((env_t.snapshot(), C::Subtype(box f2.clone(), box f.clone())));
            // Γ,¬e1 ⊢ (f3 <: f)
            c1.push_back((env_f.snapshot(), C::Subtype(box f3.clone(), box f.clone())));

            (f, c1)
        }
        Fun(ref x, ref e) => {
            let mut env = env.clone();
            let fx = k_env.fresh(&env, &Var(x.clone()));
            env.insert(x, &fx);
            let f = k_env.fresh(&env, e);
            let (fe, mut c) = cons(k_env, &env, e);
            // Γ ⊢ (x:fx → f)
            c.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,x:fx ⊢ (fe <: f)
            c.push_back((env.snapshot(), C::Subtype(box fe.clone(), box f.clone())));

            (f, c)
        }
        Fix(ref x, ref e) => {
            // const w/ ∀α.(α→α)→α
            let mut env = env.clone();
            let fx = k_env.fresh(&env, e);
            env.insert(x, &fx);

            // FIXME
            cons(k_env, &env, e)
        }
        Let(ref id, ref e1, ref e2) => {
            let mut env = env.clone();

            let f = k_env.fresh(&env, expr);
            let (f1, mut c1) = cons(k_env, &env, e1);
            env.insert(id, &f1);
            let (f2, mut c2) = cons(k_env, &env, e2);
            c1.append(&mut c2);
            // Γ ⊢ (f)
            c1.push_back((env.snapshot(), C::WellFormed(box f.clone())));
            // Γ,x:f1 ⊢ (f2 <: f)
            c1.push_back((env.snapshot(), C::Subtype(box f2.clone(), box f.clone())));

            (f, c1)
        }
        App(ref e1, ref e2) => {
            let (f1, mut c1) = cons(k_env, env, e1);
            println!("## {:?}\t:\t{:?}", e1, f1);
            let (f2, mut c2) = cons(k_env, env, e2);
            c1.append(&mut c2);
            if let T::Fun(ref x, ref fx, ref f) = f1 {
                let f = subst(x, e2, f);
                // Γ ⊢ (f2 <: fx)
                c1.push_back((env.snapshot(), C::Subtype(box f2.clone(), fx.clone())));
                return (f, c1);
            } else {
                panic!("expected TFun, not {:?}", f1);
            }
            //             let (x:Fx → F, C1) = Cons(Γ, e1) in
            // let (F
            // 0
            // x, C2) = Cons(Γ, e2) in
            // ([e2/x]F, C1 ∪ C2 ∪ {Γ ` F
            // 0
            // x <: Fx})
        }
        _ => {
            println!("unhandled {:?}", expr);
            (T::Ref(env.in_scope(), Base::Bool, box Liquid::E(Const(common::Const::Bool(true)))), LinkedList::new())
        }
    }
}

pub fn infer(expr: &Expr, env: &HashMap<Id, explicit::Type>) -> Result<Expr> {
    let mut k_env = KEnv::new(env);
    let (f, c) = cons(&mut k_env, &Env::new(env), expr);
    println!("CONS:\n");
    println!("f\t{:?}", f);
    println!("c\t{:?}", c);

    // TODO:
    // let a = Solve(Split(c), λκ.Inst(Γ, e, Q)) in
    // a(f)

    Ok(Expr::Const(common::Const::Bool(false)))
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project 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.
#![cfg(target_os = "macos")]
use std::os::raw::c_char;
use std::slice;
use std::str;
use std::env;

use objc::runtime::{Class, Object};

pub fn set_locale_environment() {
    let locale_id = unsafe {
        let locale_class = Class::get("NSLocale").unwrap();
        let locale: *const Object = msg_send![locale_class, currentLocale];
        let _ : () = msg_send![locale_class, release];
        let identifier: *const Object = msg_send![locale, localeIdentifier];
        let _ : () = msg_send![locale, release];
        let identifier_str = nsstring_as_str(identifier).to_owned();
        let _ : () = msg_send![identifier, release];
        identifier_str
    };
    let locale_id = locale_id + ".UTF-8";
    env::set_var("LANG", &locale_id);
    env::set_var("LC_CTYPE", &locale_id);
}

const UTF8_ENCODING: usize = 4;

unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str {
    let cstr: *const c_char = msg_send![nsstring, UTF8String];
    let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding:UTF8_ENCODING];
    str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap()
}

#[cfg(not(target_os = "macos"))]
pub fn set_locale_environment() {}
<commit_msg>Set $LANG env var using languageCode, countryCode<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project 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.
#![cfg(target_os = "macos")]
use std::os::raw::c_char;
use std::slice;
use std::str;
use std::env;

use objc::runtime::{Class, Object};

pub fn set_locale_environment() {
    let (language_code, country_code) = unsafe {
        let locale_class = Class::get("NSLocale").unwrap();
        let locale: *const Object = msg_send![locale_class, currentLocale];
        msg_send![locale_class, release];
        let language_code: *const Object = msg_send![locale, languageCode];
        let country_code: *const Object = msg_send![locale, countryCode];
        msg_send![locale, release];
        let language_code_str = nsstring_as_str(language_code).to_owned();
        msg_send![language_code, release];
        let country_code_str = nsstring_as_str(country_code).to_owned();
        msg_send![country_code, release];
        (language_code_str, country_code_str)
    };
    let locale_id = format!("{}_{}.UTF-8", &language_code, &country_code);
    env::set_var("LANG", &locale_id);
    // env::set_var("LC_CTYPE", &locale_id);
}

const UTF8_ENCODING: usize = 4;

unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str {
    let cstr: *const c_char = msg_send![nsstring, UTF8String];
    let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding: UTF8_ENCODING];
    str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap()
}

#[cfg(not(target_os = "macos"))]
pub fn set_locale_environment() {}
<|endoftext|>


<commit_before>use log;
use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};
use arch::drivers::serial;

use core::fmt::Write;

struct SerialLogger;

pub fn initialize() -> Result<(), log::SetLoggerError> {
    unsafe {
        log::set_logger_raw(|max_log_level| {
            static LOGGER: SerialLogger = SerialLogger;
            max_log_level.set(LogLevelFilter::Trace);
            &SerialLogger
        })
    }
}
pub fn shutdown() -> Result<(), log::ShutdownLoggerError> {
    log::shutdown_logger_raw().map(|logger| {
        let logger = unsafe { &*(logger as *const SerialLogger) };
        // logger.flush();
    })
}

#[cfg(debug_assertions)]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        true // TODO: for now?
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        match record.level() {
            LogLevel::Trace if self.enabled(meta) => {
                let location = record.location();
                write!( *serial::COM1.lock()
                      , "[ TRACE ][ {} ][ {}:{} ] {}\n"
                      , meta.target()
                      , location.module_path(), location.line()
                      , record.args() );
            }
          , LogLevel::Debug if self.enabled(meta) => {
                write!( *serial::COM1.lock()
                      , "[ TRACE ] {}: {}\n"
                      , meta.target()
                      , record.args() );
            }
          , level => {
                let target = meta.target();
                let args = record.args();
                write!( *serial::COM1.lock()
                      , "[ {} ] {}: {}\n"
                      , level, target, args );
                // println!("{}: {}", target, args );
            }
        }
    }

}

#[cfg(not(debug_assertions))]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        false // TODO: for now
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        if self.enabled(meta) {
            println!("{}: {}", target, args );
            // TODO: should we log for com1 also?
        }
    }

}
<commit_msg>[kernel] fix more serial log formatting<commit_after>use log;
use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter};
use arch::drivers::serial;

use core::fmt::Write;

struct SerialLogger;

pub fn initialize() -> Result<(), log::SetLoggerError> {
    unsafe {
        log::set_logger_raw(|max_log_level| {
            static LOGGER: SerialLogger = SerialLogger;
            max_log_level.set(LogLevelFilter::Trace);
            &SerialLogger
        })
    }
}
pub fn shutdown() -> Result<(), log::ShutdownLoggerError> {
    log::shutdown_logger_raw().map(|logger| {
        let logger = unsafe { &*(logger as *const SerialLogger) };
        // logger.flush();
    })
}

#[cfg(debug_assertions)]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        true // TODO: for now?
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        match record.level() {
            LogLevel::Trace if self.enabled(meta) => {
                let location = record.location();
                write!( *serial::COM1.lock()
                      , "[ TRACE ][ {}:{} ] target: {}\n"
                      , location.module_path(), location.line()

                      , meta.target()
                      , record.args() );
            }
          , LogLevel::Debug if self.enabled(meta) => {
                write!( *serial::COM1.lock()
                      , "[ DEBUG ] {}: {}\n"
                      , meta.target()
                      , record.args() );
            }
          , level => {
                let target = meta.target();
                let args = record.args();
                write!( *serial::COM1.lock()
                      , "[ {} ] {}: {}\n"
                      , level, target, args );
                // println!("{}: {}", target, args );
            }
        }
    }

}

#[cfg(not(debug_assertions))]
impl log::Log for SerialLogger {

    #[inline] fn enabled(&self, metadata: &LogMetadata) -> bool {
        false // TODO: for now
    }

    #[inline]
    fn log(&self, record: &LogRecord) {
        let meta = record.metadata();
        if self.enabled(meta) {
            println!("{}: {}", target, args );
            // TODO: should we log for com1 also?
        }
    }

}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! point {
  () => {{ $crate::value::Pointer::new() }};

  ($($key:expr),*) => {{
    let mut pointer = $crate::value::Pointer::new();
    $(
      pointer.push(String::from($key));
    )*
    pointer
  }}
}

#[macro_export]
macro_rules! value {
  () => {{
    $crate::value::Value::Null
  }};

  (()) => {{
    $crate::value::Value::Null
  }};

  ([$($value:tt),*]) => {{
    let mut array = $crate::value::Array::new();
    $(
      array.push(value!($value));
    )*
    $crate::value::Value::Array(array)
  }};

  ({ $($key:expr => $value:tt),* }) => {{
    let mut object = $crate::value::Object::new();
    $(
      object.insert($key.to_owned(), value!($value));
    )*
    $crate::value::Value::Object(object)
  }};

  ($value:expr) => {{
    $crate::value::Value::from($value)
  }}
}

#[cfg(test)]
macro_rules! str {
  ($value:expr) => {{
    String::from($value)
  }}
}
<commit_msg>doc(macros): add docs for macros<commit_after>/// Creates a `Pointer`. Automatically converts `&'static str` to `String` and
/// accepts more than one argument. Works like `vec!`.
///
/// # Example
/// ```rust
/// #[macro_use(point)]
/// extern crate ardite;
///
/// use ardite::value::Pointer;
///
/// # fn main() {
///
/// let mut pointer = Pointer::new();
/// pointer.push("hello".to_owned());
/// pointer.push("world".to_owned());
///
/// assert_eq!(point![], Pointer::new());
/// assert_eq!(point!["hello", "world"], pointer);
///
/// # }
/// ```
#[macro_export]
macro_rules! point {
  () => {{ $crate::value::Pointer::new() }};

  ($($key:expr),*) => {{
    let mut pointer = $crate::value::Pointer::new();
    $(
      pointer.push(String::from($key));
    )*
    pointer
  }}
}

/// Recursively create a `Value` from many primitive data types whilst also
/// detecting the appropriate type.
///
/// # Examples
/// ```rust
/// #[macro_use(value)]
/// extern crate ardite;
///
/// use ardite::value::Value;
///
/// # fn main() {
///
/// assert_eq!(value!(), Value::Null);
/// assert_eq!(value!(true), Value::Boolean(true));
/// assert_eq!(value!(42), Value::I64(42));
/// assert_eq!(value!(3.333), Value::F64(3.333));
/// assert_eq!(value!("Hello, world!"), Value::String("Hello, world!".to_owned()));
///
/// # }
/// ```
///
/// ```rust
/// #[macro_use(value)]
/// extern crate ardite;
///
/// use ardite::value::{Object, Array, Value};
///
/// # fn main() {
///
/// let value = value!([(), true, 42, 3.333, "Hello, world!", [1, 2, 3, true], { "hello" => "world" }]);
///
/// let mut array = Array::new();
/// array.push(Value::Null);
/// array.push(Value::Boolean(true));
/// array.push(Value::I64(42));
/// array.push(Value::F64(3.333));
/// array.push(Value::String("Hello, world!".to_owned()));
/// array.push(Value::Array({
///   let mut sub_array = Array::new();
///   sub_array.push(Value::I64(1));
///   sub_array.push(Value::I64(2));
///   sub_array.push(Value::I64(3));
///   sub_array.push(Value::Boolean(true));
///   sub_array
/// }));
/// array.push(Value::Object({
///   let mut object = Object::new();
///   object.insert("hello".to_owned(), Value::String("world".to_owned()));
///   object
/// }));
///
/// assert_eq!(value, Value::Array(array));
///
/// # }
/// ```
///
/// ```rust
/// #[macro_use(value)]
/// extern crate ardite;
///
/// use ardite::value::{Object, Array, Value};
///
/// # fn main() {
///
/// let value = value!({
///   "null" => (),
///   "boolean" => true,
///   "integer" => 42,
///   "float" => 3.333,
///   "string" => "Hello, world!",
///   "array" => [1, 2, 3, true],
///   "object" => {
///     "hello" => "world"
///   }
/// });
///
/// let mut object = Object::new();
/// object.insert("null".to_owned(), Value::Null);
/// object.insert("boolean".to_owned(), Value::Boolean(true));
/// object.insert("integer".to_owned(), Value::I64(42));
/// object.insert("float".to_owned(), Value::F64(3.333));
/// object.insert("string".to_owned(), Value::String("Hello, world!".to_owned()));
/// object.insert("array".to_owned(), Value::Array({
///   let mut array = Array::new();
///   array.push(Value::I64(1));
///   array.push(Value::I64(2));
///   array.push(Value::I64(3));
///   array.push(Value::Boolean(true));
///   array
/// }));
/// object.insert("object".to_owned(), Value::Object({
///   let mut sub_object = Object::new();
///   sub_object.insert("hello".to_owned(), Value::String("world".to_owned()));
///   sub_object
/// }));
///
/// assert_eq!(value, Value::Object(object));
///
/// # }
/// ```
#[macro_export]
macro_rules! value {
  () => {{
    $crate::value::Value::Null
  }};

  (()) => {{
    $crate::value::Value::Null
  }};

  ([$($value:tt),*]) => {{
    let mut array = $crate::value::Array::new();
    $(
      array.push(value!($value));
    )*
    $crate::value::Value::Array(array)
  }};

  ({ $($key:expr => $value:tt),* }) => {{
    let mut object = $crate::value::Object::new();
    $(
      object.insert($key.to_owned(), value!($value));
    )*
    $crate::value::Value::Object(object)
  }};

  ($value:expr) => {{
    $crate::value::Value::from($value)
  }}
}

#[cfg(test)]
macro_rules! str {
  ($value:expr) => {{
    String::from($value)
  }}
}
<|endoftext|>


<commit_before>
/// A macro for extracting the result from a `Poll<T, E>`.
///
/// Turns the `Poll<T, E>` into a `Result<T, F>` by early returning a
/// possible `Ok(Async::NotReady)` and calling `F::from()` for an error.
#[macro_export]
macro_rules! try_result {
    ($e:expr) => (match $e {
        Ok($crate::Async::Ready(t)) => Ok(t),
        Ok($crate::Async::NotReady) => return Ok($crate::Async::NotReady),
        Err(e) => Err(From::from(e)),
    })
}

<commit_msg>Add an alt! macro.<commit_after>
/// A macro for extracting the result from a `Poll<T, E>`.
///
/// Turns the `Poll<T, E>` into a `Result<T, E>` by early returning a
/// possible `Ok(Async::NotReady)`.
#[macro_export]
macro_rules! try_result {
    ($e:expr) => (match $e {
        Ok($crate::Async::Ready(t)) => Ok(t),
        Ok($crate::Async::NotReady) => return Ok($crate::Async::NotReady),
        Err(e) => Err(e),
    })
}

#[macro_export]
macro_rules! alt {
    ( $e:expr, $( $tail:tt )* ) => {{
        match $e {
            Ok($crate::Async::Ready(t)) => Ok($crate::Async::Ready(t)),
            Ok($crate::Async::NotReady) => Ok($crate::Async::NotReady),
            Err(_) => {
                alt!( $( $tail )* )
            }
        }
    }};

    ( $e:expr ) => {{
        match $e {
            Ok($crate::Async::Ready(t)) => Ok($crate::Async::Ready(t)),
            Ok($crate::Async::NotReady) => Ok($crate::Async::NotReady),
            Err(err) => Err(err),
        }
    }};

}
<|endoftext|>