<commit_before>use tile::{Tile,Bbox};
use std::cmp::min;
use std::f32;
use utils::search_closest_idx;

pub const TILE_SIZE: usize = 256;

/// Holds data and provides methods to regrid data into a 256 x 256 grid.
#[derive(Debug)]
pub struct TileData {
    /// Must be expressed in meters, in ascending order
    pub lat: Vec<f64>,
    /// Must be expressed in meters, in ascending order
    pub lon: Vec<f64>,
    /// Values must be a flattened array (lat, lon)
    pub values: Vec<f32>,
    pub bbox: Bbox,
    pub tile: Tile,
}
impl TileData {

    /**
     * regrid self.values into a TILE_SIZE x TILE_SIZE grid.
     */
    pub fn to_tile_grid(&self) -> [[f32; TILE_SIZE]; TILE_SIZE] {

        // fetch nearest latitudes indices
        let mut lat_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lat_inc: f64 = (self.bbox.north -self.bbox.south) / (TILE_SIZE as f64);

        let lats: Vec<f64> = (0..TILE_SIZE).map(|i| {
            self.bbox.south + lat_inc * (0.5 + i as f64)
        }).collect();
        for (i, lat) in lats.iter().enumerate() {
            lat_ids[i] = search_closest_idx(&self.lat, lat).unwrap();
        }

        // fetch nearest longitude indices
        let mut lon_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lon_inc: f64 = (self.bbox.east - self.bbox.west) / (TILE_SIZE as f64);

        let lons: Vec<f64> = (0..TILE_SIZE).map(|i| {
            self.bbox.west + lon_inc * (0.5 + i as f64)
        }).collect();
        for (i, lon) in lons.iter().enumerate() {
            lon_ids[i] = search_closest_idx(&self.lon, lon).unwrap();
        }

        // pick values using precomputed indices
        let mut values: [[f32; TILE_SIZE]; TILE_SIZE] = [
            [f32::NAN; TILE_SIZE];
            TILE_SIZE
        ];
        if self.values.len() > TILE_SIZE * TILE_SIZE {
            for i_lat in 0..TILE_SIZE {
                for i_lon in 0..TILE_SIZE {
                    values[i_lat][i_lon] = self.value_at(lat_ids[i_lat], lon_ids[i_lon]);
                }
            }

        } else {
            for (i_lat, lat) in lats.iter().enumerate() {
                for (i_lon, lon) in lons.iter().enumerate() {
                    //values[i_lat][i_lon] = self.value_at(lat_ids[i_lat], lon_ids[i_lon]);
                    values[i_lat][i_lon] = self.interpolate_value_at(
                        *lat,
                        *lon,
                        lat_ids[i_lat],
                        lon_ids[i_lon]
                    );
                }
            }
        }
        //println!("{}, {}", self.lat.len(), self.lon.len());
        values
    }

    fn interpolate_value_at( &self, requested_lat: f64, requested_lon: f64, lat_idx: usize, lon_idx: usize) ->  f32 {

        let mut can_interp_lon = (lon_idx > 0 || self.lon[lon_idx] < requested_lon)
               && (lon_idx < self.lon.len()-1 || self.lon[lon_idx] > requested_lon);
        let mut can_interp_lat = (lat_idx > 0 || self.lat[lat_idx] < requested_lat)
               && (lat_idx < self.lat.len()-1 || self.lat[lat_idx] > requested_lat);

        can_interp_lon &= requested_lon != self.lon[lon_idx];
        can_interp_lat &= requested_lat != self.lat[lat_idx];

        let interp_between = | va: f32, a: f64, vb: f32, b: f64, x: f64 | -> f32 {
            if (a - b).abs() > 10. && (x -a).abs() > 10. && (x-b).abs() > 10. {
                ((va as f64 * (x - b).abs() + vb as f64 * (x - a).abs()) / (a - b).abs()) as f32
            } else {
                if (x-a).abs() < (x-b).abs() {
                    return va;
                }
                return vb;
            }
        };
        let other_lon_idx: usize = if requested_lon > self.lon[lon_idx] {
            lon_idx +1 } else { lon_idx -1 };
        let other_lat_idx: usize = if requested_lat > self.lat[lat_idx] {
            lat_idx +1 } else { lat_idx -1 };

        if can_interp_lon && can_interp_lat {
            let val_aa = self.value_at(lat_idx, lon_idx);
            let val_ab = self.value_at(lat_idx, other_lon_idx);
            let val_ba = self.value_at(other_lat_idx, lon_idx);
            let val_bb = self.value_at(other_lat_idx, other_lon_idx);
            let a = interp_between(
                val_aa,
                self.lon[lon_idx],
                val_ab,
                self.lon[other_lon_idx],
                requested_lon
            );
            let b = interp_between(
                val_ba,
                self.lon[lon_idx],
                val_bb,
                self.lon[other_lon_idx],
                requested_lon
            );

            return interp_between(
                a,
                self.lat[lat_idx],
                b,
                self.lat[other_lat_idx],
                requested_lat
            );
        } else if can_interp_lon {
            return interp_between(
                self.value_at(lat_idx, lon_idx),
                self.lon[lon_idx],
                self.value_at(lat_idx, other_lon_idx),
                self.lon[other_lon_idx],
                requested_lon
            );
        } else if can_interp_lat {
            return interp_between(
                self.value_at(lat_idx, lon_idx),
                self.lat[lat_idx],
                self.value_at(lat_idx, lon_idx),
                self.lat[other_lat_idx],
                requested_lat
            );
        } else {
            return self.value_at(lat_idx, lon_idx);
        }
    }

    #[inline]
    /// Return the value of self.values as if it was a bi-dimensional array.
    fn value_at(&self, lat_idx: usize, lon_idx: usize) -> f32 {
        return self.values[self.lon.len() * lat_idx + lon_idx];
    }

    /// Creates up to 4 tiles, representing the n+1 zoom level using self.values
    pub fn sub_tiledata(&self) -> Vec<Self> {
        let mut sub_tiledata: Vec<Self> = Vec::new();
        let base_x = self.tile.x * 2;
        let base_y = self.tile.y * 2;
        let z = self.tile.z + 1;
        for x in  base_x..(base_x + 2) {
            for y in base_y..(base_y + 2) {
                let tile = Tile { x: x, y: y, z: z };
                let xy = tile.xy_bounds();

                // get min latitude index
                let mut i_lat_min: usize = 0;
                for (i, lat) in self.lat.iter().enumerate() {
                    if *lat >= xy.south {
                        i_lat_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max latitude index
                let mut i_lat_max: usize = 0;
                for (i, lat) in self.lat.iter().rev().enumerate() {
                    if *lat <= xy.north {
                        i_lat_max = if i != (self.lat.len() - 1 ) { self.lat.len() - i } else { self.lat.len() -1 };
                        break;
                    }
                }

                // get min longitude index
                let mut i_lon_min: usize = 0;
                for (i, lon) in self.lon.iter().enumerate() {
                    if *lon >= xy.west {
                        i_lon_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max longitude index
                let mut i_lon_max: usize = 0;
                for (i, lon) in self.lon.iter().rev().enumerate() {
                    if *lon <= xy.east {
                        i_lon_max = if i != (self.lon.len() - 1 ) { self.lon.len() - i } else { self.lon.len() -1 };
                        break;
                    }
                }

                // Extract lat, lon and values using the computed indices
                let subset_lat: Vec<f64> = self.lat[i_lat_min..min(i_lat_max +1, self.lat.len() -1)].to_vec();
                let subset_lon: Vec<f64> = self.lon[i_lon_min..min(i_lon_max +1, self.lon.len() -1)].to_vec();
                let mut subset_values: Vec<f32> = Vec::with_capacity(subset_lat.len() * subset_lon.len());
                for i_lat in i_lat_min..min(i_lat_max +1, self.lat.len() -1) {
                    for i_lon in i_lon_min..min(i_lon_max +1, self.lon.len() -1) {
                        subset_values.push(self.value_at(i_lat, i_lon));
                    }
                }

                sub_tiledata.push(
                    Self {
                        lon: subset_lon,
                        lat: subset_lat,
                        values: subset_values,
                        bbox: xy,
                        tile: tile
                    }
                );
            }
        }
        sub_tiledata
    }
}
<commit_msg>Added bilinear interpolation<commit_after>use tile::{Tile,Bbox};
use std::cmp::min;
use std::f32;
use utils::search_closest_idx;

pub const TILE_SIZE: usize = 256;

/// Holds data and provides methods to regrid data into a 256 x 256 grid.
#[derive(Debug)]
pub struct TileData {
    /// Must be expressed in meters, in ascending order
    pub lat: Vec<f64>,
    /// Must be expressed in meters, in ascending order
    pub lon: Vec<f64>,
    /// Values must be a flattened array (lat, lon)
    pub values: Vec<f32>,
    pub bbox: Bbox,
    pub tile: Tile,
}

impl TileData {

    /**
     * regrid self.values into a TILE_SIZE x TILE_SIZE grid.
     */
    pub fn to_tile_grid(&self) -> [[f32; TILE_SIZE]; TILE_SIZE] {

        // Build latitude needed for each pixel
        let lat_inc: f64 = (self.bbox.north -self.bbox.south) / (TILE_SIZE as f64);
        let lats: Vec<f64> = (0..TILE_SIZE).map(|i| {
            self.bbox.south + lat_inc * (0.5 + i as f64)
        }).collect();

        // Build longitude needed for each pixel
        let lon_inc: f64 = (self.bbox.east - self.bbox.west) / (TILE_SIZE as f64);
        let lons: Vec<f64> = (0..TILE_SIZE).map(|i| {
            self.bbox.west + lon_inc * (0.5 + i as f64)
        }).collect();

        // Build output values
        let mut values: [[f32; TILE_SIZE]; TILE_SIZE] = [
            [f32::NAN; TILE_SIZE];
            TILE_SIZE
        ];
        // directly fetch the nearest data or interpole it
        // depending of the number of data available
        if self.values.len() > TILE_SIZE * TILE_SIZE {
            // directly fetch the nearest data for each pixel
            for (i_lat, lat) in lats.iter().enumerate() {
                for (i_lon, lon) in lons.iter().enumerate() {
                    let lat_idx = search_closest_idx(&self.lat, lat).unwrap();
                    let lon_idx = search_closest_idx(&self.lon, lon).unwrap();
                    values[i_lat][i_lon] = self.value_at(lat_idx, lon_idx);
                }
            }
        } else {
            // interpolate each pixel value
            for (i_lat, lat) in lats.iter().enumerate() {
                for (i_lon, lon) in lons.iter().enumerate() {
                    values[i_lat][i_lon] = self.interpolate_value_at(*lat, *lon);
                }
            }
        }
        values
    }

    /// This function fetch and interpolate the data from self.value, self.lon, self.lat
    /// at the requested lat / lon.
    /// It basically performs a bilinear interpolation
    fn interpolate_value_at( &self, requested_lat: f64, requested_lon: f64) ->  f32 {
        // fetch nearest longitude / latitude indices
        let lat_idx = search_closest_idx(&self.lat, &requested_lat).unwrap();
        let lon_idx = search_closest_idx(&self.lon, &requested_lon).unwrap();

        // see if we can interpolate the data, we need 4 points inside the bounding
        // box of self.lon ans self.lat
        let can_interp_lon = (lon_idx > 0 || self.lon[lon_idx] < requested_lon)
               && (lon_idx < self.lon.len()-1 || self.lon[lon_idx] > requested_lon);
        let can_interp_lat = (lat_idx > 0 || self.lat[lat_idx] < requested_lat)
               && (lat_idx < self.lat.len()-1 || self.lat[lat_idx] > requested_lat);

        // this function interpolate a value between 2 other
        // * `a` and `b` are the position of the 2 input points,
        // * `va` and `vb` are their values.
        // * `x` is the position where the output value will be expressed
        let interp_between = | va: f32, a: f64, vb: f32, b: f64, x: f64 | -> f32 {
            let vx =  va * ((x - b).abs() / (a - b).abs()) as f32
             +  vb * ((x - a).abs() / (a - b).abs()) as f32;
            // because of the float precision, we need to filter aberrant values
            // generated by the interpolation
            if vx > vb && vx > va {
                // return the closest
                if (a - x).abs() > (b - x).abs() {
                    return vb;
                }
                return va;
            }
            return vx;
        };

        // get the indices of the other points needed to interpolate
        let other_lon_idx: usize = if requested_lon > self.lon[lon_idx] {
            lon_idx +1 } else { lon_idx -1 };
        let other_lat_idx: usize = if requested_lat > self.lat[lat_idx] {
            lat_idx +1 } else { lat_idx -1 };

        if can_interp_lon && can_interp_lat {
            // First interpolate linearly the 4 points at the requested longitude
            let a = interp_between(
                self.value_at(lat_idx, lon_idx),
                self.lon[lon_idx],
                self.value_at(lat_idx, other_lon_idx),
                self.lon[other_lon_idx],
                requested_lon
            );
            let b = interp_between(
                self.value_at(other_lat_idx, lon_idx),
                self.lon[lon_idx],
                self.value_at(other_lat_idx, other_lon_idx),
                self.lon[other_lon_idx],
                requested_lon
            );
            // finally interpolate at the requested latitude
            return interp_between(
                a,
                self.lat[lat_idx],
                b,
                self.lat[other_lat_idx],
                requested_lat
            );
        } else if can_interp_lon {
            // only interpolate at the requested longitude
            return interp_between(
                self.value_at(lat_idx, lon_idx),
                self.lon[lon_idx],
                self.value_at(lat_idx, other_lon_idx),
                self.lon[other_lon_idx],
                requested_lon
            );
        } else if can_interp_lat {
            // only interpolate at the requested latitude
            return interp_between(
                self.value_at(lat_idx, lon_idx),
                self.lat[lat_idx],
                self.value_at(lat_idx, lon_idx),
                self.lat[other_lat_idx],
                requested_lat
            );
        } else {
            // If we can't interpolate, returns the nearest value
            return self.value_at(lat_idx, lon_idx);
        }
    }

    #[inline]
    /// Return the value of self.values as if it was a bi-dimensional array.
    fn value_at(&self, lat_idx: usize, lon_idx: usize) -> f32 {
        return self.values[self.lon.len() * lat_idx + lon_idx];
    }

    /// Creates up to 4 tiles, representing the n+1 zoom level using self.values
    pub fn sub_tiledata(&self) -> Vec<Self> {
        // TODO: Use binary search
        let mut sub_tiledata: Vec<Self> = Vec::new();
        let base_x = self.tile.x * 2;
        let base_y = self.tile.y * 2;
        let z = self.tile.z + 1;
        for x in  base_x..(base_x + 2) {
            for y in base_y..(base_y + 2) {
                let tile = Tile { x: x, y: y, z: z };
                let xy = tile.xy_bounds();

                // get min latitude index
                let mut i_lat_min: usize = 0;
                for (i, lat) in self.lat.iter().enumerate() {
                    if *lat >= xy.south {
                        i_lat_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max latitude index
                let mut i_lat_max: usize = 0;
                for (i, lat) in self.lat.iter().rev().enumerate() {
                    if *lat <= xy.north {
                        i_lat_max = if i != (self.lat.len() - 1 ) { self.lat.len() - i } else { self.lat.len() -1 };
                        break;
                    }
                }

                // get min longitude index
                let mut i_lon_min: usize = 0;
                for (i, lon) in self.lon.iter().enumerate() {
                    if *lon >= xy.west {
                        i_lon_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max longitude index
                let mut i_lon_max: usize = 0;
                for (i, lon) in self.lon.iter().rev().enumerate() {
                    if *lon <= xy.east {
                        i_lon_max = if i != (self.lon.len() - 1 ) { self.lon.len() - i } else { self.lon.len() -1 };
                        break;
                    }
                }

                // Extract lat, lon and values using the computed indices
                let subset_lat: Vec<f64> = self.lat[i_lat_min..min(i_lat_max +1, self.lat.len() -1)].to_vec();
                let subset_lon: Vec<f64> = self.lon[i_lon_min..min(i_lon_max +1, self.lon.len() -1)].to_vec();
                let mut subset_values: Vec<f32> = Vec::with_capacity(subset_lat.len() * subset_lon.len());
                for i_lat in i_lat_min..min(i_lat_max +1, self.lat.len() -1) {
                    for i_lon in i_lon_min..min(i_lon_max +1, self.lon.len() -1) {
                        subset_values.push(self.value_at(i_lat, i_lon));
                    }
                }

                sub_tiledata.push(
                    Self {
                        lon: subset_lon,
                        lat: subset_lat,
                        values: subset_values,
                        bbox: xy,
                        tile: tile
                    }
                );
            }
        }
        sub_tiledata
    }
}
<|endoftext|>


<commit_before>use base64;
use r2pipe::{R2Pipe, R2};
use radeco_lib;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::interproc::fixcall::CallFixer;
use radeco_lib::analysis::sccp;
use radeco_lib::backend::lang_c::c_cfg::ctrl_flow_struct;
use radeco_lib::backend::lang_c::c_cfg::CCFGVerifier;
use radeco_lib::backend::lang_c::c_cfg_builder;
use radeco_lib::frontend::radeco_containers::*;
use radeco_lib::middle::ir_writer;
use radeco_lib::middle::regfile::SubRegisterFile;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ssa::verifier;
use radeco_lib::middle::{dce, dot};
use std::cell::RefCell;
use std::collections::HashMap;
use std::panic;
use std::rc::Rc;
use std::str;
use std::sync::Arc;

thread_local!(pub static PROJ: RefCell<Option<RadecoProject>> = RefCell::new(None););

pub fn fn_list(proj: &RadecoProject) -> Vec<String> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .map(|s| s.name.to_string())
        .collect()
}

pub fn get_function<'a>(name: &str, proj: &'a RadecoProject) -> Option<&'a RadecoFunction> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .filter(|rfn| rfn.name == name)
        .next()
}

pub fn get_function_mut<'a>(
    name: &str,
    proj: &'a mut RadecoProject,
) -> Option<&'a mut RadecoFunction> {
    proj.iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut())
        .filter(|rfn| rfn.name == name)
        .next()
}

pub fn fn_rename(old_f: &str, new_f: &str, proj: &mut RadecoProject) {
    if let Some(_) = get_function(new_f, proj) {
        println!("there is already a function called: {}", new_f);
        return;
    }

    let mut found = false;

    for module in proj.iter_mut() {
        let module = module.module;
        let off = module.iter()
            .find(|rfn| rfn.function.1.name == old_f)
            .map(|rfn| rfn.function.1.offset);

        if let Some(off) = off {
            module.function_rename(off, new_f);
            found = true;
        }
    }

    if !found {
        println!("function not found: {}", old_f);
    }
}

pub fn analyze_mod(regfile: Arc<SubRegisterFile>, rmod: &mut RadecoModule) {
    // Analyze preserved for all functions.
    {
        eprintln!("[*] Fixing Callee Information");
        let bp_name = regfile.get_name_by_alias(&"BP".to_string());
        let bp_name = bp_name.map(|s| s.to_owned());
        let sp_name = regfile.get_name_by_alias(&"SP".to_string());
        let sp_name = sp_name.map(|s| s.to_owned());
        let mut callfixer = CallFixer::new(rmod, bp_name, sp_name);
        callfixer.rounded_analysis();
    }

    // Fix call sites
    radeco_lib::analysis::functions::fix_ssa_opcalls::go(rmod);

    // Infer calling conventions
    radeco_lib::analysis::functions::infer_regusage::run(rmod, &*regfile);
}

pub fn analyze(rfn: &mut RadecoFunction) {
    eprintln!("[+] Analyzing: {} @ {:#x}", rfn.name, rfn.offset);
    {
        eprintln!("  [*] Eliminating Dead Code");
        dce::collect(rfn.ssa_mut());
    }
    let mut ssa = {
        // Constant Propagation (sccp)
        eprintln!("  [*] Propagating Constants");
        let mut analyzer = sccp::Analyzer::new(rfn.ssa_mut());
        analyzer.analyze();
        analyzer.emit_ssa()
    };
    {
        eprintln!("  [*] Eliminating More DeadCode");
        dce::collect(&mut ssa);
    }
    *rfn.ssa_mut() = ssa;
    {
        // Common SubExpression Elimination (cse)
        eprintln!("  [*] Eliminating Common SubExpressions");
        let mut cse = CSE::new(rfn.ssa_mut());
        cse.run();
    }
    {
        // Verify SSA
        eprintln!("  [*] Verifying SSA's Validity");
        match verifier::verify(rfn.ssa()) {
            Err(e) => {
                eprintln!("  [*] Found Error: {}", e);
            }
            Ok(_) => {}
        }
    }
}

pub fn analyze_all_functions<'a>(proj: &'a mut RadecoProject) {
    let rfns = proj
        .iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut());
    for rfn in rfns {
        analyze(rfn);
    }
}

pub fn emit_ir(rfn: &RadecoFunction) -> String {
    eprintln!("  [*] Writing out IR");
    let mut res = String::new();
    ir_writer::emit_il(&mut res, Some(rfn.name.to_string()), rfn.ssa()).unwrap();
    res
}

pub fn emit_dot(ssa: &SSAStorage) -> String {
    dot::emit_dot(ssa)
}

pub fn decompile_all_functions<'a>(proj: &'a RadecoProject) -> String {
    let mut decompiled_funcs = Vec::new();
    let funcs = fn_list(&proj);
    for f in &funcs {
        match decompile(f, &proj) {
            Ok(res) => {
                decompiled_funcs.push(res);
            }
            Err(err) => {
                eprintln!("{}", err);
            }
        };
    }
    decompiled_funcs.join("\n")
}

pub fn decompile<'a>(name: &str, proj: &'a RadecoProject) -> Result<String, String> {
    if let Some(rfn) = get_function(name, &proj) {
        let rmod = proj.iter().map(|i| i.module).next().unwrap();
        let func_name_map = func_names(&rmod);
        let strings = strings(&rmod);
        decompile_priv(rfn, &func_name_map, &strings)
    } else {
        Err(format!("{} is not found.", name))
    }
}

fn decompile_priv(
    rfn: &RadecoFunction,
    func_name_map: &HashMap<u64, String>,
    strings: &HashMap<u64, String>,
) -> Result<String, String> {
    let c_cfg_result =
        panic::catch_unwind(|| c_cfg_builder::recover_c_cfg(rfn, func_name_map, strings));

    if c_cfg_result.is_err() {
        return Err("Failed to recover C control flow graph".to_string());
    };

    let c_cfg = c_cfg_result.unwrap();

    if let Err(err) = CCFGVerifier::verify(&c_cfg) {
        eprintln!("CCFG verification failed {}", err);
    }

    let result = panic::catch_unwind(|| {
        ctrl_flow_struct::structure_and_convert(c_cfg.clone())
            .map(|s| s.print())
            .map_err(|e| e.to_string())
    });
    match result {
        Ok(code) => code,
        Err(_) => {
            println!("Control flow structuring failed");
            Ok(c_cfg.to_c_ast().print())
        }
    }
}

pub fn load_proj_by_path(path: &str) -> RadecoProject {
    let mut p = ProjectLoader::new().path(path).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

pub fn load_proj_tcp(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::tcp(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

pub fn load_proj_http(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::http(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

pub fn load_project_by_r2pipe(r2p: R2Pipe) -> RadecoProject {
    let r2 = R2::from(r2p);
    let r2w = Rc::new(RefCell::new(r2));
    let mut p = ProjectLoader::new().source(Rc::new(r2w)).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

pub fn func_names(rmod: &RadecoModule) -> HashMap<u64, String> {
    rmod.functions
        .iter()
        .map(|(&addr, f)| (addr, f.name.to_string()))
        .collect()
}

pub fn strings(rmod: &RadecoModule) -> HashMap<u64, String> {
    rmod.strings()
        .iter()
        .filter(|ref s| s.paddr.is_some() && s.string.is_some())
        .cloned()
        .map(|s| {
            let (addr, _s) = (s.vaddr.unwrap(), s.string.unwrap());
            let bytes = base64::decode(&_s).unwrap_or(Vec::new());
            let ret_string = match str::from_utf8(bytes.as_slice()) {
                Ok(v) => v.to_string(),
                Err(_e) => _s,
            };
            (addr, ret_string)
        })
        .collect()
}
<commit_msg>Apply inst_combine<commit_after>use base64;
use r2pipe::{R2Pipe, R2};
use radeco_lib;
use radeco_lib::analysis::cse::cse::CSE;
use radeco_lib::analysis::inst_combine;
use radeco_lib::analysis::interproc::fixcall::CallFixer;
use radeco_lib::analysis::sccp;
use radeco_lib::backend::lang_c::c_cfg::ctrl_flow_struct;
use radeco_lib::backend::lang_c::c_cfg::CCFGVerifier;
use radeco_lib::backend::lang_c::c_cfg_builder;
use radeco_lib::frontend::radeco_containers::*;
use radeco_lib::middle::ir_writer;
use radeco_lib::middle::regfile::SubRegisterFile;
use radeco_lib::middle::ssa::ssastorage::SSAStorage;
use radeco_lib::middle::ssa::verifier;
use radeco_lib::middle::{dce, dot};
use std::cell::RefCell;
use std::collections::HashMap;
use std::panic;
use std::rc::Rc;
use std::str;
use std::sync::Arc;

thread_local!(pub static PROJ: RefCell<Option<RadecoProject>> = RefCell::new(None););

pub fn fn_list(proj: &RadecoProject) -> Vec<String> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .map(|s| s.name.to_string())
        .collect()
}

pub fn get_function<'a>(name: &str, proj: &'a RadecoProject) -> Option<&'a RadecoFunction> {
    proj.iter()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values())
        .filter(|rfn| rfn.name == name)
        .next()
}

pub fn get_function_mut<'a>(
    name: &str,
    proj: &'a mut RadecoProject,
) -> Option<&'a mut RadecoFunction> {
    proj.iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut())
        .filter(|rfn| rfn.name == name)
        .next()
}

pub fn fn_rename(old_f: &str, new_f: &str, proj: &mut RadecoProject) {
    if let Some(_) = get_function(new_f, proj) {
        println!("there is already a function called: {}", new_f);
        return;
    }

    let mut found = false;

    for module in proj.iter_mut() {
        let module = module.module;
        let off = module.iter()
            .find(|rfn| rfn.function.1.name == old_f)
            .map(|rfn| rfn.function.1.offset);

        if let Some(off) = off {
            module.function_rename(off, new_f);
            found = true;
        }
    }

    if !found {
        println!("function not found: {}", old_f);
    }
}

pub fn analyze_mod(regfile: Arc<SubRegisterFile>, rmod: &mut RadecoModule) {
    // Analyze preserved for all functions.
    {
        eprintln!("[*] Fixing Callee Information");
        let bp_name = regfile.get_name_by_alias(&"BP".to_string());
        let bp_name = bp_name.map(|s| s.to_owned());
        let sp_name = regfile.get_name_by_alias(&"SP".to_string());
        let sp_name = sp_name.map(|s| s.to_owned());
        let mut callfixer = CallFixer::new(rmod, bp_name, sp_name);
        callfixer.rounded_analysis();
    }

    // Fix call sites
    radeco_lib::analysis::functions::fix_ssa_opcalls::go(rmod);

    // Infer calling conventions
    radeco_lib::analysis::functions::infer_regusage::run(rmod, &*regfile);
}

pub fn analyze(rfn: &mut RadecoFunction) {
    eprintln!("[+] Analyzing: {} @ {:#x}", rfn.name, rfn.offset);
    {
        eprintln!("  [*] Eliminating Dead Code");
        dce::collect(rfn.ssa_mut());
    }
    let mut ssa = {
        // Constant Propagation (sccp)
        eprintln!("  [*] Propagating Constants");
        let mut analyzer = sccp::Analyzer::new(rfn.ssa_mut());
        analyzer.analyze();
        analyzer.emit_ssa()
    };
    {
        eprintln!("  [*] Eliminating More DeadCode");
        dce::collect(&mut ssa);
    }
    *rfn.ssa_mut() = ssa;
    inst_combine::run(rfn.ssa_mut());
    {
        // Common SubExpression Elimination (cse)
        eprintln!("  [*] Eliminating Common SubExpressions");
        let mut cse = CSE::new(rfn.ssa_mut());
        cse.run();
    }
    {
        // Verify SSA
        eprintln!("  [*] Verifying SSA's Validity");
        match verifier::verify(rfn.ssa()) {
            Err(e) => {
                eprintln!("  [*] Found Error: {}", e);
            }
            Ok(_) => {}
        }
    }
}

pub fn analyze_all_functions<'a>(proj: &'a mut RadecoProject) {
    let rfns = proj
        .iter_mut()
        .map(|i| i.module)
        .flat_map(|rmod| rmod.functions.values_mut());
    for rfn in rfns {
        analyze(rfn);
    }
}

pub fn emit_ir(rfn: &RadecoFunction) -> String {
    eprintln!("  [*] Writing out IR");
    let mut res = String::new();
    ir_writer::emit_il(&mut res, Some(rfn.name.to_string()), rfn.ssa()).unwrap();
    res
}

pub fn emit_dot(ssa: &SSAStorage) -> String {
    dot::emit_dot(ssa)
}

pub fn decompile_all_functions<'a>(proj: &'a RadecoProject) -> String {
    let mut decompiled_funcs = Vec::new();
    let funcs = fn_list(&proj);
    for f in &funcs {
        match decompile(f, &proj) {
            Ok(res) => {
                decompiled_funcs.push(res);
            }
            Err(err) => {
                eprintln!("{}", err);
            }
        };
    }
    decompiled_funcs.join("\n")
}

pub fn decompile<'a>(name: &str, proj: &'a RadecoProject) -> Result<String, String> {
    if let Some(rfn) = get_function(name, &proj) {
        let rmod = proj.iter().map(|i| i.module).next().unwrap();
        let func_name_map = func_names(&rmod);
        let strings = strings(&rmod);
        decompile_priv(rfn, &func_name_map, &strings)
    } else {
        Err(format!("{} is not found.", name))
    }
}

fn decompile_priv(
    rfn: &RadecoFunction,
    func_name_map: &HashMap<u64, String>,
    strings: &HashMap<u64, String>,
) -> Result<String, String> {
    let c_cfg_result =
        panic::catch_unwind(|| c_cfg_builder::recover_c_cfg(rfn, func_name_map, strings));

    if c_cfg_result.is_err() {
        return Err("Failed to recover C control flow graph".to_string());
    };

    let c_cfg = c_cfg_result.unwrap();

    if let Err(err) = CCFGVerifier::verify(&c_cfg) {
        eprintln!("CCFG verification failed {}", err);
    }

    let result = panic::catch_unwind(|| {
        ctrl_flow_struct::structure_and_convert(c_cfg.clone())
            .map(|s| s.print())
            .map_err(|e| e.to_string())
    });
    match result {
        Ok(code) => code,
        Err(_) => {
            println!("Control flow structuring failed");
            Ok(c_cfg.to_c_ast().print())
        }
    }
}

pub fn load_proj_by_path(path: &str) -> RadecoProject {
    let mut p = ProjectLoader::new().path(path).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

pub fn load_proj_tcp(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::tcp(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

pub fn load_proj_http(url: &str) -> Result<RadecoProject, &'static str> {
    let r2p = R2Pipe::http(url)?;
    Ok(load_project_by_r2pipe(r2p))
}

pub fn load_project_by_r2pipe(r2p: R2Pipe) -> RadecoProject {
    let r2 = R2::from(r2p);
    let r2w = Rc::new(RefCell::new(r2));
    let mut p = ProjectLoader::new().source(Rc::new(r2w)).load();
    let regfile = p.regfile().clone();
    for mut xy in p.iter_mut() {
        analyze_mod(regfile.clone(), xy.module);
    }
    p
}

pub fn func_names(rmod: &RadecoModule) -> HashMap<u64, String> {
    rmod.functions
        .iter()
        .map(|(&addr, f)| (addr, f.name.to_string()))
        .collect()
}

pub fn strings(rmod: &RadecoModule) -> HashMap<u64, String> {
    rmod.strings()
        .iter()
        .filter(|ref s| s.paddr.is_some() && s.string.is_some())
        .cloned()
        .map(|s| {
            let (addr, _s) = (s.vaddr.unwrap(), s.string.unwrap());
            let bytes = base64::decode(&_s).unwrap_or(Vec::new());
            let ret_string = match str::from_utf8(bytes.as_slice()) {
                Ok(v) => v.to_string(),
                Err(_e) => _s,
            };
            (addr, ret_string)
        })
        .collect()
}
<|endoftext|>


<commit_before>use std::fmt;

use error::ConversionError;

#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]
pub enum Type {
    Void,
    Integer,
    Float,
    Bool,
    Str, /* Array, */
}

#[derive(Debug,Clone,PartialEq)]
pub enum Value {
    Void,
    Integer(i32),
    Float(f32),
    Bool(bool),
    Str(String), /* Array, */
}

impl Value {
    pub fn truthy(&self) -> Result<bool, ConversionError> {
        use self::Value::*;

        match *self {
            Integer(0) => Ok(false),
            Integer(_) => Ok(true),
            Float(0f32) => Ok(false),
            Float(_) => Ok(true),
            Bool(false) => Ok(false),
            Bool(true) => Ok(true),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Bool)),
            Void => Err(ConversionError::new(Type::Void, Type::Bool)),
        }
    }

    pub fn get_type(&self) -> Type {
        use self::Value::*;

        match *self {
            Void => Type::Void,
            Integer(_) => Type::Integer,
            Float(_) => Type::Float,
            Bool(_) => Type::Bool,
            Str(_) => Type::Str,
        }
    }

    pub fn into_int(self) -> Result<Self, ConversionError> {
        use self::Value::*;

        match self {
            Integer(_) => Ok(self),
            Float(val) => Ok(Integer(val as i32)),
            Bool(val) => Ok(Integer(val as i32)),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Integer)),
            Void => Err(ConversionError::new(Type::Void, Type::Integer)),
        }
    }

    pub fn into_float(self) -> Result<Self, ConversionError> {
        use self::Value::*;

        match self {
            Integer(val) => Ok(Float(val as f32)),
            Float(_) => Ok(self),
            Bool(val) => Ok(Float(if val { 1f32 } else { 0f32 })),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Float)),
            Void => Err(ConversionError::new(Type::Void, Type::Float)),
        }
    }
}

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

        match *self {
            Integer(ref value) => write!(f, "{}", value),
            Float(ref value) => write!(f, "{}", value),
            Bool(ref value) => write!(f, "{}", value),
            Str(ref value) => write!(f, "{}", value),
            Void => Err(fmt::Error::default()),
        }
    }
}

pub fn unescape_str(input: String) -> String {
    let mut res = String::with_capacity(input.len());

    let mut chars = input.chars();

    while let Some(ch) = chars.next() {
        res.push(if ch != '\\' {
                     ch
                 } else {
                     match chars.next() {
                         Some('n') => '\n',
                         Some('r') => '\r',
                         Some('t') => '\t',
                         Some(ch) => ch,
                         None => panic!("Un-ended string"),
                     }
                 });
    }

    res
}
<commit_msg>Adding codepoint escapes in string literals<commit_after>use std::char;
use std::fmt;

use error::ConversionError;

#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]
pub enum Type {
    Void,
    Integer,
    Float,
    Bool,
    Str, /* Array, */
}

#[derive(Debug,Clone,PartialEq)]
pub enum Value {
    Void,
    Integer(i32),
    Float(f32),
    Bool(bool),
    Str(String), /* Array, */
}

impl Value {
    pub fn truthy(&self) -> Result<bool, ConversionError> {
        use self::Value::*;

        match *self {
            Integer(0) => Ok(false),
            Integer(_) => Ok(true),
            Float(0f32) => Ok(false),
            Float(_) => Ok(true),
            Bool(false) => Ok(false),
            Bool(true) => Ok(true),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Bool)),
            Void => Err(ConversionError::new(Type::Void, Type::Bool)),
        }
    }

    pub fn get_type(&self) -> Type {
        use self::Value::*;

        match *self {
            Void => Type::Void,
            Integer(_) => Type::Integer,
            Float(_) => Type::Float,
            Bool(_) => Type::Bool,
            Str(_) => Type::Str,
        }
    }

    pub fn into_int(self) -> Result<Self, ConversionError> {
        use self::Value::*;

        match self {
            Integer(_) => Ok(self),
            Float(val) => Ok(Integer(val as i32)),
            Bool(val) => Ok(Integer(val as i32)),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Integer)),
            Void => Err(ConversionError::new(Type::Void, Type::Integer)),
        }
    }

    pub fn into_float(self) -> Result<Self, ConversionError> {
        use self::Value::*;

        match self {
            Integer(val) => Ok(Float(val as f32)),
            Float(_) => Ok(self),
            Bool(val) => Ok(Float(if val { 1f32 } else { 0f32 })),
            Str(_) => Err(ConversionError::new(Type::Str, Type::Float)),
            Void => Err(ConversionError::new(Type::Void, Type::Float)),
        }
    }
}

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

        match *self {
            Integer(ref value) => write!(f, "{}", value),
            Float(ref value) => write!(f, "{}", value),
            Bool(ref value) => write!(f, "{}", value),
            Str(ref value) => write!(f, "{}", value),
            Void => Err(fmt::Error::default()),
        }
    }
}

pub fn unescape_str(input: String) -> String {
    let mut res = String::with_capacity(input.len());

    let mut chars = input.chars();

    while let Some(ch) = chars.next() {
        res.push(if ch != '\\' {
                     ch
                 } else {
                     match chars.next() {
                         Some('x') => {
                             chars
                                 .by_ref()
                                 .take(2)
                                 .fold(0u8,
                                       |acc, c| acc * 16 + c.to_digit(16).unwrap() as u8) as char
                         }
                         Some('u') => {
                             let val = chars
                                 .by_ref()
                                 .take(4)
                                 .fold(0,
                                       |acc, c| acc * 16 + c.to_digit(16).unwrap());
                             char::from_u32(val).unwrap()
                         }
                         Some('n') => '\n',
                         Some('r') => '\r',
                         Some('t') => '\t',
                         Some(ch) => ch,
                         None => panic!("Un-ended string"),
                     }
                 });
    }

    res
}
<|endoftext|>


<commit_before>use std::f32::consts::PI;

use collect_slice::CollectSlice;
use num::complex::Complex32;
use num::traits::Zero;
use quad_osc::QuadOsc;

use consts::SAMPLES_PER_FRAME;
use descramble::VoiceDecisions;
use enhance::EnhancedSpectrals;
use noise::Noise;
use params::BaseParams;
use window;

// Result of equation 121
const SCALING_COEF: f32 = 146.6432708443356;

const DFT_SIZE: usize = 256;
const IDFT_SIZE: usize = 256;

const DFT_HALF: usize = DFT_SIZE / 2;
const IDFT_HALF: usize = IDFT_SIZE / 2;

const SIG_START: isize = -104;
const SIG_STOP: isize = 105;
const SIG_SIZE: usize = (SIG_STOP - SIG_START) as usize;

fn edges(l: usize, params: &BaseParams) -> (usize, usize) {
    let common = DFT_SIZE as f32 / (2.0 * PI) * params.fundamental;

    (
        (common * (l as f32 - 0.5)).ceil() as usize,
        (common * (l as f32 + 0.5)).ceil() as usize,
    )
}

pub struct UnvoicedDFT([Complex32; DFT_HALF]);

impl UnvoicedDFT {
    pub fn new(params: &BaseParams, voice: &VoiceDecisions, enhanced: &EnhancedSpectrals)
        -> UnvoicedDFT
    {
        let sig = {
            let mut sig = [0.0; SIG_SIZE];

            let mut noise = Noise::new();
            let window = window::synthesis();

            (SIG_START..SIG_STOP)
                .map(|n| noise.next() * window.get(n))
                .collect_slice_checked(&mut sig[..]);

            sig
        };

        let mut dft = [Complex32::zero(); DFT_HALF];

        for (l, &spectral) in enhanced.iter().enumerate() {
            let l = l + 1;

            if voice.is_voiced(l) {
                continue;
            }

            let (lower, upper) = edges(l, params);

            for m in lower..upper {
                let common = 2.0 / DFT_SIZE as f32 * PI * m as f32;
                let mut osc = QuadOsc::new(common * SIG_START as f32, common);

                dft[m] = sig.iter().map(|&x| {
                    let (sin, cos) = osc.next();
                    x * Complex32::new(cos, -sin)
                }).fold(Complex32::zero(), |s, x| s + x)
            }

            let energy = (lower..upper)
                .map(|m| dft[m].norm_sqr())
                .fold(0.0, |s, x| s + x);
            let power = energy / (upper - lower) as f32;
            let scale = SCALING_COEF * spectral / power.sqrt();

            for m in lower..upper {
                dft[m] = scale * dft[m];
            }
        }

        UnvoicedDFT(dft)
    }

    pub fn idft(&self, n: isize) -> f32 {
        if n < -(IDFT_HALF as isize) || n >= IDFT_HALF as isize {
            return 0.0;
        }

        let mut osc = QuadOsc::new(0.0, 2.0 / IDFT_SIZE as f32 * PI * n as f32);

        2.0 / (DFT_SIZE as f32 * IDFT_SIZE as f32).sqrt() * (0..DFT_HALF).map(|m| {
            let (sin, cos) = osc.next();
            self.0[m].re * cos - self.0[m].im * sin
        }).fold(0.0, |s, x| s + x)
    }
}

impl Default for UnvoicedDFT {
    fn default() -> UnvoicedDFT {
        UnvoicedDFT([Complex32::zero(); DFT_HALF])
    }
}

pub struct Unvoiced<'a, 'b> {
    cur: &'a UnvoicedDFT,
    prev: &'b UnvoicedDFT,
    window: window::Window,
}

impl<'a, 'b> Unvoiced<'a, 'b> {
    pub fn new(cur: &'a UnvoicedDFT, prev: &'b UnvoicedDFT) -> Unvoiced<'a, 'b> {
        Unvoiced {
            cur: cur,
            prev: prev,
            window: window::synthesis(),
        }
    }

    pub fn get(&self, n: usize) -> f32 {
        let n = n as isize;

        let numer = self.window.get(n) * self.prev.idft(n) +
            self.window.get(n - SAMPLES_PER_FRAME as isize) * self.cur.idft(n - SAMPLES_PER_FRAME as isize);
        let denom = self.window.get(n).powi(2) +
            self.window.get(n - SAMPLES_PER_FRAME as isize).powi(2);

        numer / denom
    }
}

#[cfg(test)]
mod test {
    use super::edges;
    use descramble::Bootstrap;
    use params::BaseParams;

    #[test]
    fn test_edges() {
        let chunks = [
            0b001000010010,
            0b110011001100,
            0b111000111000,
            0b111111111111,
            0b10100110101,
            0b00101111010,
            0b01110111011,
            0b00001000,
        ];

        let b = Bootstrap::new(&chunks);
        let p = BaseParams::new(b.unwrap_period());

        assert!((p.fundamental - 0.17575344).abs() < 0.000001);

        let (lower, upper) = edges(1, &p);
        assert_eq!(lower, 4);
        assert_eq!(upper, 11);

        let (lower, upper) = edges(2, &p);
        assert_eq!(lower, 11);
        assert_eq!(upper, 18);

        let (lower, upper) = edges(5, &p);
        assert_eq!(lower, 33);
        assert_eq!(upper, 40);

        let (lower, upper) = edges(8, &p);
        assert_eq!(lower, 54);
        assert_eq!(upper, 61);

        let (lower, upper) = edges(16, &p);
        assert_eq!(lower, 111);
        assert_eq!(upper, 119);
    }
}
<commit_msg>s/spectral/amplitude/<commit_after>use std::f32::consts::PI;

use collect_slice::CollectSlice;
use num::complex::Complex32;
use num::traits::Zero;
use quad_osc::QuadOsc;

use consts::SAMPLES_PER_FRAME;
use descramble::VoiceDecisions;
use enhance::EnhancedSpectrals;
use noise::Noise;
use params::BaseParams;
use window;

// Result of equation 121
const SCALING_COEF: f32 = 146.6432708443356;

const DFT_SIZE: usize = 256;
const IDFT_SIZE: usize = 256;

const DFT_HALF: usize = DFT_SIZE / 2;
const IDFT_HALF: usize = IDFT_SIZE / 2;

const SIG_START: isize = -104;
const SIG_STOP: isize = 105;
const SIG_SIZE: usize = (SIG_STOP - SIG_START) as usize;

fn edges(l: usize, params: &BaseParams) -> (usize, usize) {
    let common = DFT_SIZE as f32 / (2.0 * PI) * params.fundamental;

    (
        (common * (l as f32 - 0.5)).ceil() as usize,
        (common * (l as f32 + 0.5)).ceil() as usize,
    )
}

pub struct UnvoicedDFT([Complex32; DFT_HALF]);

impl UnvoicedDFT {
    pub fn new(params: &BaseParams, voice: &VoiceDecisions, enhanced: &EnhancedSpectrals)
        -> UnvoicedDFT
    {
        let sig = {
            let mut sig = [0.0; SIG_SIZE];

            let mut noise = Noise::new();
            let window = window::synthesis();

            (SIG_START..SIG_STOP)
                .map(|n| noise.next() * window.get(n))
                .collect_slice_checked(&mut sig[..]);

            sig
        };

        let mut dft = [Complex32::zero(); DFT_HALF];

        for (l, &amplitude) in enhanced.iter().enumerate() {
            let l = l + 1;

            if voice.is_voiced(l) {
                continue;
            }

            let (lower, upper) = edges(l, params);

            for m in lower..upper {
                let common = 2.0 / DFT_SIZE as f32 * PI * m as f32;
                let mut osc = QuadOsc::new(common * SIG_START as f32, common);

                dft[m] = sig.iter().map(|&x| {
                    let (sin, cos) = osc.next();
                    x * Complex32::new(cos, -sin)
                }).fold(Complex32::zero(), |s, x| s + x)
            }

            let energy = (lower..upper)
                .map(|m| dft[m].norm_sqr())
                .fold(0.0, |s, x| s + x);
            let power = energy / (upper - lower) as f32;
            let scale = SCALING_COEF * amplitude / power.sqrt();

            for m in lower..upper {
                dft[m] = scale * dft[m];
            }
        }

        UnvoicedDFT(dft)
    }

    pub fn idft(&self, n: isize) -> f32 {
        if n < -(IDFT_HALF as isize) || n >= IDFT_HALF as isize {
            return 0.0;
        }

        let mut osc = QuadOsc::new(0.0, 2.0 / IDFT_SIZE as f32 * PI * n as f32);

        2.0 / (DFT_SIZE as f32 * IDFT_SIZE as f32).sqrt() * (0..DFT_HALF).map(|m| {
            let (sin, cos) = osc.next();
            self.0[m].re * cos - self.0[m].im * sin
        }).fold(0.0, |s, x| s + x)
    }
}

impl Default for UnvoicedDFT {
    fn default() -> UnvoicedDFT {
        UnvoicedDFT([Complex32::zero(); DFT_HALF])
    }
}

pub struct Unvoiced<'a, 'b> {
    cur: &'a UnvoicedDFT,
    prev: &'b UnvoicedDFT,
    window: window::Window,
}

impl<'a, 'b> Unvoiced<'a, 'b> {
    pub fn new(cur: &'a UnvoicedDFT, prev: &'b UnvoicedDFT) -> Unvoiced<'a, 'b> {
        Unvoiced {
            cur: cur,
            prev: prev,
            window: window::synthesis(),
        }
    }

    pub fn get(&self, n: usize) -> f32 {
        let n = n as isize;

        let numer = self.window.get(n) * self.prev.idft(n) +
            self.window.get(n - SAMPLES_PER_FRAME as isize) * self.cur.idft(n - SAMPLES_PER_FRAME as isize);
        let denom = self.window.get(n).powi(2) +
            self.window.get(n - SAMPLES_PER_FRAME as isize).powi(2);

        numer / denom
    }
}

#[cfg(test)]
mod test {
    use super::edges;
    use descramble::Bootstrap;
    use params::BaseParams;

    #[test]
    fn test_edges() {
        let chunks = [
            0b001000010010,
            0b110011001100,
            0b111000111000,
            0b111111111111,
            0b10100110101,
            0b00101111010,
            0b01110111011,
            0b00001000,
        ];

        let b = Bootstrap::new(&chunks);
        let p = BaseParams::new(b.unwrap_period());

        assert!((p.fundamental - 0.17575344).abs() < 0.000001);

        let (lower, upper) = edges(1, &p);
        assert_eq!(lower, 4);
        assert_eq!(upper, 11);

        let (lower, upper) = edges(2, &p);
        assert_eq!(lower, 11);
        assert_eq!(upper, 18);

        let (lower, upper) = edges(5, &p);
        assert_eq!(lower, 33);
        assert_eq!(upper, 40);

        let (lower, upper) = edges(8, &p);
        assert_eq!(lower, 54);
        assert_eq!(upper, 61);

        let (lower, upper) = edges(16, &p);
        assert_eq!(lower, 111);
        assert_eq!(upper, 119);
    }
}
<|endoftext|>


<commit_before>//! This pass is overloaded and runs two different lints.
//!
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests.

use super::{span_of_attrs, Pass};
use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use crate::visit_ast::inherits_doc_hidden;
use rustc_middle::lint::LintLevelSource;
use rustc_session::lint;
use rustc_span::symbol::sym;

crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
    name: "check-private-items-doc-tests",
    run: check_private_items_doc_tests,
    description: "check private items doc tests",
};

struct PrivateItemDocTestLinter<'a, 'tcx> {
    cx: &'a mut DocContext<'tcx>,
}

crate fn check_private_items_doc_tests(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
    let mut coll = PrivateItemDocTestLinter { cx };

    coll.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);

        look_for_tests(self.cx, &dox, &item);

        Some(self.fold_item_recur(item))
    }
}

pub(crate) struct Tests {
    pub(crate) found_tests: usize,
}

impl crate::doctest::Tester for Tests {
    fn add_test(&mut self, _: String, config: LangString, _: usize) {
        if config.rust && config.ignore == Ignore::None {
            self.found_tests += 1;
        }
    }
}

crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
    if !cx.renderinfo.borrow().access_levels.is_public(item.def_id)
        || matches!(
            *item.kind,
            clean::StructFieldItem(_)
                | clean::VariantItem(_)
                | clean::AssocConstItem(_, _)
                | clean::AssocTypeItem(_, _)
                | clean::TypedefItem(_, _)
                | clean::StaticItem(_)
                | clean::ConstantItem(_)
                | clean::ExternCrateItem(_, _)
                | clean::ImportItem(_)
                | clean::PrimitiveItem(_)
                | clean::KeywordItem(_)
        )
    {
        return false;
    }
    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
    if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
        || inherits_doc_hidden(cx.tcx, hir_id)
    {
        return false;
    }
    let (level, source) = cx.tcx.lint_level_at_node(crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id);
    level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
}

crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
    let hir_id = match cx.as_local_hir_id(item.def_id) {
        Some(hir_id) => hir_id,
        None => {
            // If non-local, no need to check anything.
            return;
        }
    };

    let mut tests = Tests { found_tests: 0 };

    find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);

    if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() {
        if should_have_doc_example(cx, &item) {
            debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
            let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
            cx.tcx.struct_span_lint_hir(
                crate::lint::MISSING_DOC_CODE_EXAMPLES,
                hir_id,
                sp,
                |lint| lint.build("missing code example in this documentation").emit(),
            );
        }
    } else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id) {
        cx.tcx.struct_span_lint_hir(
            crate::lint::PRIVATE_DOC_TESTS,
            hir_id,
            span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
            |lint| lint.build("documentation test in private item").emit(),
        );
    }
}
<commit_msg>No more need for borrow call<commit_after>//! This pass is overloaded and runs two different lints.
//!
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests.

use super::{span_of_attrs, Pass};
use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use crate::visit_ast::inherits_doc_hidden;
use rustc_middle::lint::LintLevelSource;
use rustc_session::lint;
use rustc_span::symbol::sym;

crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
    name: "check-private-items-doc-tests",
    run: check_private_items_doc_tests,
    description: "check private items doc tests",
};

struct PrivateItemDocTestLinter<'a, 'tcx> {
    cx: &'a mut DocContext<'tcx>,
}

crate fn check_private_items_doc_tests(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
    let mut coll = PrivateItemDocTestLinter { cx };

    coll.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);

        look_for_tests(self.cx, &dox, &item);

        Some(self.fold_item_recur(item))
    }
}

pub(crate) struct Tests {
    pub(crate) found_tests: usize,
}

impl crate::doctest::Tester for Tests {
    fn add_test(&mut self, _: String, config: LangString, _: usize) {
        if config.rust && config.ignore == Ignore::None {
            self.found_tests += 1;
        }
    }
}

crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
    if !cx.renderinfo.access_levels.is_public(item.def_id)
        || matches!(
            *item.kind,
            clean::StructFieldItem(_)
                | clean::VariantItem(_)
                | clean::AssocConstItem(_, _)
                | clean::AssocTypeItem(_, _)
                | clean::TypedefItem(_, _)
                | clean::StaticItem(_)
                | clean::ConstantItem(_)
                | clean::ExternCrateItem(_, _)
                | clean::ImportItem(_)
                | clean::PrimitiveItem(_)
                | clean::KeywordItem(_)
        )
    {
        return false;
    }
    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
    if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
        || inherits_doc_hidden(cx.tcx, hir_id)
    {
        return false;
    }
    let (level, source) = cx.tcx.lint_level_at_node(crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id);
    level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
}

crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
    let hir_id = match cx.as_local_hir_id(item.def_id) {
        Some(hir_id) => hir_id,
        None => {
            // If non-local, no need to check anything.
            return;
        }
    };

    let mut tests = Tests { found_tests: 0 };

    find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);

    if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() {
        if should_have_doc_example(cx, &item) {
            debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
            let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
            cx.tcx.struct_span_lint_hir(
                crate::lint::MISSING_DOC_CODE_EXAMPLES,
                hir_id,
                sp,
                |lint| lint.build("missing code example in this documentation").emit(),
            );
        }
    } else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id) {
        cx.tcx.struct_span_lint_hir(
            crate::lint::PRIVATE_DOC_TESTS,
            hir_id,
            span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
            |lint| lint.build("documentation test in private item").emit(),
        );
    }
}
<|endoftext|>


<commit_before>mod my {
    // A public struct with public fields
    pub struct WhiteBox<T> {
        pub contents: T,
    }

    // A public struct with private fields
    #[allow(dead_code)]
    pub struct BlackBox<T> {
        contents: T,
    }

    impl<T> BlackBox<T> {
        // A public constructor
        pub fn new(contents: T) -> BlackBox<T> {
            BlackBox {
                contents: contents,
            }
        }
    }
}

fn main() {
    // Public structs with public fields can be constructed as usual
    let white_box = my::WhiteBox { contents: "public information" };

    // and their fields can be normally accessed
    println!("The white box contains: {}", white_box.contents);

    // but public structs with private fields can't be constructed
    // Error! `BlackBox` has private fields
    //let black_box = my::BlackBox { contents: "classified information" };
    // TODO ^ Try uncommenting this line

    // However, structs with private fields can still be created using
    // constructors
    let _black_box = my::BlackBox::new("classified information");

    // The private fields of a struct can't be accessed
    // Error! The `contents` field is private
    //println!("The black box contains: {}", black_box.contents);
    // TODO ^ Try uncommenting this line
}
<commit_msg>Update struct.rs<commit_after>mod my {
    // A public struct with public fields
    pub struct WhiteBox<T> {
        pub contents: T,
    }

    // A public struct with private fields
    #[allow(dead_code)]
    pub struct BlackBox<T> {
        contents: T,
    }

    impl<T> BlackBox<T> {
        // A public constructor
        pub fn new(contents: T) -> BlackBox<T> {
            BlackBox {
                contents: contents,
            }
        }
    }
}

fn main() {
    // Public structs with public fields can be constructed as usual
    let white_box = my::WhiteBox { contents: "public information" };

    // and their fields can be normally accessed
    println!("The white box contains: {}", white_box.contents);

    // but public structs with private fields can't be constructed
    // Error! `BlackBox` has private fields
    //let black_box = my::BlackBox { contents: "classified information" };
    // TODO ^ Try uncommenting this line

    // However, structs with private fields can still be created using
    // constructors
    let _black_box = my::BlackBox::new("classified information");

    // The private fields of a struct can't be accessed
    // Error! The `contents` field is private
    //println!("The black box contains: {}", _black_box.contents);
    // TODO ^ Try uncommenting this line
}
<|endoftext|>


<commit_before>use std::vec::FromVec;
use module::*;
use scoped_map::ScopedMap;
use interner::*;

///A Name is a reference to a specific identifier in the program, guaranteed to be unique
#[deriving(PartialEq, Eq, Hash, Clone)]
pub struct Name {
    pub name: InternedStr,
    pub uid: uint
}

impl Str for Name {
    fn as_slice<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }
}

impl ::std::fmt::Show for Name {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{}_{}", self.name, self.uid)
    }
}

///Generic struct which can store and report errors
struct Errors<T> {
    errors: Vec<T>
}
impl <T> Errors<T> {
    fn new() -> Errors<T> {
        Errors { errors: Vec::new() }
    }
    fn insert(&mut self, e: T) {
        self.errors.push(e);
    }
    fn has_errors(&self) -> bool {
        self.errors.len() != 0
    }
}
impl <T: ::std::fmt::Show> Errors<T> {
    fn report_errors(&self, pass: &str) {
        println!("Found {} errors in compiler pass: {}", self.errors.len(), pass);
        for error in self.errors.iter() {
            println!("{}", error);
        }
    }
}

///A NameSupply can turn simple strings into unique Names
pub struct NameSupply {
    unique_id: uint
}
impl NameSupply {

    pub fn new() -> NameSupply {
        NameSupply { unique_id: 0 }
    }
    ///Create a unique Name which are anonymous
    pub fn anonymous(&mut self) -> Name {
        self.from_str("_a")
    }
    ///Takes a string and returns a new Name which is unique
    pub fn from_str(&mut self, s: &str) -> Name {
        self.from_interned(intern(s))
    }
    ///Takes a string and returns a new Name which is unique
    pub fn from_interned(&mut self, s: InternedStr) -> Name {
        Name { name: s, uid: self.next_id() }
    }
    pub fn next_id(&mut self) -> uint {
        self.unique_id += 1;
        self.unique_id
    }
}

///The renamer has methods which turns the ASTs identifiers from simple strings
///into unique Names
struct Renamer {
    ///Mapping of strings into the unique name
    uniques: ScopedMap<InternedStr, Name>,
    name_supply: NameSupply,
    ///All errors found while renaming are stored here
    errors: Errors<String>
}

impl Renamer {
    fn new() -> Renamer {
        Renamer { uniques: ScopedMap::new(), name_supply: NameSupply::new(), errors: Errors::new() }
    }

    fn rename_bindings(&mut self, bindings: ~[Binding<InternedStr>], is_global: bool) -> ~[Binding<Name>] {
        //Add all bindings in the scope
        for bind in binding_groups(bindings.as_slice()) {
            self.make_unique(bind[0].name.clone());
            if is_global {
                self.uniques.find_mut(&bind[0].name).unwrap().uid = 0;
            }
        }
        FromVec::<Binding<Name>>::from_vec(bindings.move_iter().map(|binding| {
            let Binding { name: name, arguments: arguments, matches: matches, typ: typ, where: where  } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            self.uniques.enter_scope();
            let b = Binding {
                name: n,
                arguments: self.rename_arguments(arguments),
                where: where.map(|bs| self.rename_bindings(bs, false)),
                matches: self.rename_matches(matches),
                typ: typ,
            };
            self.uniques.exit_scope();
            b
        }).collect())
    }

    fn rename(&mut self, input_expr: TypedExpr<InternedStr>) -> TypedExpr<Name> {
        let TypedExpr { expr: expr, typ: typ, location: location } = input_expr;
        let e = match expr {
            Literal(l) => Literal(l),
            Identifier(i) => Identifier(self.get_name(i)),
            Apply(func, arg) => Apply(box self.rename(*func), box self.rename(*arg)),
            OpApply(lhs, op, rhs) => OpApply(box self.rename(*lhs), self.get_name(op), box self.rename(*rhs)),
            Lambda(arg, body) => {
                self.uniques.enter_scope();
                let l = Lambda(self.rename_pattern(arg), box self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings, false);
                let l = Let(bs, box self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a: Vec<Alternative<Name>> = alts.move_iter().map(|alt| {
                    let Alternative {
                        pattern: Located { location: loc, node: pattern },
                        matches: matches,
                        where: where
                    } = alt;
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: Located { location: loc, node: self.rename_pattern(pattern) },
                        where: where.map(|bs| self.rename_bindings(bs, false)),
                        matches: self.rename_matches(matches)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(box self.rename(*expr), FromVec::from_vec(a))
            }
            IfElse(pred, if_true, if_false) => {
                IfElse(box self.rename(*pred),
                       box self.rename(*if_true),
                       box self.rename(*if_false))
            }
            Do(bindings, expr) => {
                let bs: Vec<DoBinding<Name>> = bindings.move_iter().map(|bind| {
                    match bind {
                        DoExpr(expr) => DoExpr(self.rename(expr)),
                        DoLet(bs) => DoLet(self.rename_bindings(bs, false)),
                        DoBind(pattern, expr) => {
                            let Located { location: location, node: node } = pattern;
                            let loc = Located { location: location, node: self.rename_pattern(node) };
                            DoBind(loc, self.rename(expr))
                        }
                    }
                }).collect();
                Do(FromVec::from_vec(bs), box self.rename(*expr))
            }
            TypeSig(expr, sig) => {
                TypeSig(box self.rename(*expr), sig)
            }
            Paren(expr) => Paren(box self.rename(*expr))
        };
        let mut t = TypedExpr::with_location(e, location);
        t.typ = typ;
        t
    }

    fn rename_pattern(&mut self, pattern: Pattern<InternedStr>) -> Pattern<Name> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2: Vec<Pattern<Name>> = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(Name { name: s, uid: 0}, FromVec::from_vec(ps2))
            }
            IdentifierPattern(s) => IdentifierPattern(self.make_unique(s)),
            WildCardPattern => WildCardPattern
        }
    }
    ///Turns the string into the Name which is currently in scope
    ///If the name was not found it is assumed to be global
    fn get_name(&self, s: InternedStr) -> Name {
        match self.uniques.find(&s) {
            Some(&Name { uid: uid, .. }) => Name { name: s, uid: uid },
            None => Name { name: s, uid: 0 }//If the variable is not found in variables it is a global variable
        }
    }

    fn rename_matches(&mut self, matches: Match<InternedStr>) -> Match<Name> {
        match matches {
            Simple(e) => Simple(self.rename(e)),
            Guards(gs) => Guards(FromVec::<Guard<Name>>::from_vec(
                gs.move_iter()
                .map(|Guard { predicate: p, expression: e }|
                      Guard { predicate: self.rename(p), expression: self.rename(e) }
                )
                .collect()))
        }
    }

    fn rename_arguments(&mut self, arguments: ~[Pattern<InternedStr>]) -> ~[Pattern<Name>] {
        FromVec::<Pattern<Name>>::from_vec(arguments.move_iter().map(|a| self.rename_pattern(a)).collect())
    }

    ///Introduces a new Name to the current scope.
    ///If the name was already declared in the current scope an error is added
    fn make_unique(&mut self, name: InternedStr) -> Name {
        if self.uniques.in_current_scope(&name) {
            self.errors.insert(format!("{} is defined multiple times", name));
            self.uniques.find(&name).map(|x| x.clone()).unwrap()
        }
        else {
            let u = self.name_supply.from_interned(name.clone());
            self.uniques.insert(name, u.clone());
            u
        }
    }
}

pub fn rename_expr(expr: TypedExpr<InternedStr>) -> TypedExpr<Name> {
    let mut renamer = Renamer::new();
    renamer.rename(expr)
}

pub fn rename_module(module: Module<InternedStr>) -> Module<Name> {
    let mut renamer = Renamer::new();
    rename_module_(&mut renamer, module)
}
pub fn rename_module_(renamer: &mut Renamer, module: Module<InternedStr>) -> Module<Name> {
    let Module {
        name: name,
        imports: imports,
        classes : classes,
        dataDefinitions: data_definitions,
        newtypes: newtypes,
        typeDeclarations: typeDeclarations,
        bindings : bindings,
        instances: instances,
        fixity_declarations: fixity_declarations
    } = module;

    let data_definitions2 : Vec<DataDefinition<Name>> = data_definitions.move_iter().map(|data| {
        let DataDefinition {
            constructors : ctors,
            typ : typ,
            parameters : parameters,
            deriving
        } = data;
        let c: Vec<Constructor<Name>> = ctors.move_iter().map(|ctor| {
            let Constructor {
                name : name,
                typ : typ,
                tag : tag,
                arity : arity
            } = ctor;
            Constructor {
                name : Name { name: name, uid: 0 },
                typ : typ,
                tag : tag,
                arity : arity
            }
        }).collect();

        let d: Vec<Name> = deriving.move_iter().map(|s| {
            Name { name: s, uid: 0 }
        }).collect();

        DataDefinition {
            typ : typ,
            parameters : parameters,
            constructors : FromVec::from_vec(c),
            deriving : FromVec::from_vec(d)
        }
    }).collect();

    let newtypes2: Vec<Newtype<Name>> = newtypes.move_iter().map(|newtype| {
        fail!()
    }).collect();

    let instances2: Vec<Instance<Name>> = instances.move_iter().map(|instance| {
        let Instance {
            bindings : bindings,
            constraints : constraints,
            typ : typ,
            classname : classname
        } = instance;
        Instance {
            bindings : renamer.rename_bindings(bindings, true),
            constraints : constraints,
            typ : typ,
            classname : classname
        }
    }).collect();

    let classes2 : Vec<Class<Name>> = classes.move_iter().map(|class| {
        let Class {
            constraints: cs,
            name : name,
            variable : var,
            declarations : decls,
            bindings: bindings
        } = class;
        Class {
            constraints: cs,
            name: name,
            variable: var,
            declarations: decls,
            bindings: renamer.rename_bindings(bindings, true)
        }
    }).collect();

    let bindings2 = renamer.rename_bindings(bindings, true);

    let fixity_declarations2: Vec<FixityDeclaration<Name>> = fixity_declarations.move_iter()
        .map(|FixityDeclaration { assoc: assoc, precedence: precedence, operators: operators }| {

            let ops: Vec<Name> = operators.move_iter()
                .map(|s| renamer.get_name(s))
                .collect();
            FixityDeclaration { assoc: assoc, precedence: precedence,
                operators: FromVec::from_vec(ops)
            }
        })
        .collect();

    Module {
        name: renamer.make_unique(name),
        imports: imports,
        classes : FromVec::from_vec(classes2),
        dataDefinitions: FromVec::from_vec(data_definitions2),
        typeDeclarations: typeDeclarations,
        bindings : bindings2,
        instances: FromVec::from_vec(instances2),
        newtypes: FromVec::from_vec(newtypes2),
        fixity_declarations: FromVec::from_vec(fixity_declarations2)
    }
}

///Renames a vector of modules.
///If any errors are encounterd while renaming, an error message is output and fail is called
pub fn rename_modules(modules: Vec<Module<InternedStr>>) -> Vec<Module<Name>> {
    let mut renamer = Renamer::new();
    let ms = modules.move_iter().map(|module| {
        rename_module_(&mut renamer, module)
    }).collect();
    if renamer.errors.has_errors() {
        renamer.errors.report_errors("Renamer");
        fail!();
    }
    ms
}

#[cfg(test)]
mod tests {
    use renamer::*;
    use parser::*;
    #[test]
    #[should_fail]
    fn duplicate_binding() {
        let mut parser = Parser::new(
r"main = 1
test = []
main = 2".chars());
        let module = parser.module();
        rename_modules(vec!(module));
    }
}
<commit_msg>Renaming of Newtype implemented<commit_after>use std::vec::FromVec;
use module::*;
use scoped_map::ScopedMap;
use interner::*;

///A Name is a reference to a specific identifier in the program, guaranteed to be unique
#[deriving(PartialEq, Eq, Hash, Clone)]
pub struct Name {
    pub name: InternedStr,
    pub uid: uint
}

impl Str for Name {
    fn as_slice<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }
}

impl ::std::fmt::Show for Name {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{}_{}", self.name, self.uid)
    }
}

///Generic struct which can store and report errors
struct Errors<T> {
    errors: Vec<T>
}
impl <T> Errors<T> {
    fn new() -> Errors<T> {
        Errors { errors: Vec::new() }
    }
    fn insert(&mut self, e: T) {
        self.errors.push(e);
    }
    fn has_errors(&self) -> bool {
        self.errors.len() != 0
    }
}
impl <T: ::std::fmt::Show> Errors<T> {
    fn report_errors(&self, pass: &str) {
        println!("Found {} errors in compiler pass: {}", self.errors.len(), pass);
        for error in self.errors.iter() {
            println!("{}", error);
        }
    }
}

///A NameSupply can turn simple strings into unique Names
pub struct NameSupply {
    unique_id: uint
}
impl NameSupply {

    pub fn new() -> NameSupply {
        NameSupply { unique_id: 0 }
    }
    ///Create a unique Name which are anonymous
    pub fn anonymous(&mut self) -> Name {
        self.from_str("_a")
    }
    ///Takes a string and returns a new Name which is unique
    pub fn from_str(&mut self, s: &str) -> Name {
        self.from_interned(intern(s))
    }
    ///Takes a string and returns a new Name which is unique
    pub fn from_interned(&mut self, s: InternedStr) -> Name {
        Name { name: s, uid: self.next_id() }
    }
    pub fn next_id(&mut self) -> uint {
        self.unique_id += 1;
        self.unique_id
    }
}

///The renamer has methods which turns the ASTs identifiers from simple strings
///into unique Names
struct Renamer {
    ///Mapping of strings into the unique name
    uniques: ScopedMap<InternedStr, Name>,
    name_supply: NameSupply,
    ///All errors found while renaming are stored here
    errors: Errors<String>
}

impl Renamer {
    fn new() -> Renamer {
        Renamer { uniques: ScopedMap::new(), name_supply: NameSupply::new(), errors: Errors::new() }
    }

    fn rename_bindings(&mut self, bindings: ~[Binding<InternedStr>], is_global: bool) -> ~[Binding<Name>] {
        //Add all bindings in the scope
        for bind in binding_groups(bindings.as_slice()) {
            self.make_unique(bind[0].name.clone());
            if is_global {
                self.uniques.find_mut(&bind[0].name).unwrap().uid = 0;
            }
        }
        FromVec::<Binding<Name>>::from_vec(bindings.move_iter().map(|binding| {
            let Binding { name: name, arguments: arguments, matches: matches, typ: typ, where: where  } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            self.uniques.enter_scope();
            let b = Binding {
                name: n,
                arguments: self.rename_arguments(arguments),
                where: where.map(|bs| self.rename_bindings(bs, false)),
                matches: self.rename_matches(matches),
                typ: typ,
            };
            self.uniques.exit_scope();
            b
        }).collect())
    }

    fn rename(&mut self, input_expr: TypedExpr<InternedStr>) -> TypedExpr<Name> {
        let TypedExpr { expr: expr, typ: typ, location: location } = input_expr;
        let e = match expr {
            Literal(l) => Literal(l),
            Identifier(i) => Identifier(self.get_name(i)),
            Apply(func, arg) => Apply(box self.rename(*func), box self.rename(*arg)),
            OpApply(lhs, op, rhs) => OpApply(box self.rename(*lhs), self.get_name(op), box self.rename(*rhs)),
            Lambda(arg, body) => {
                self.uniques.enter_scope();
                let l = Lambda(self.rename_pattern(arg), box self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings, false);
                let l = Let(bs, box self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a: Vec<Alternative<Name>> = alts.move_iter().map(|alt| {
                    let Alternative {
                        pattern: Located { location: loc, node: pattern },
                        matches: matches,
                        where: where
                    } = alt;
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: Located { location: loc, node: self.rename_pattern(pattern) },
                        where: where.map(|bs| self.rename_bindings(bs, false)),
                        matches: self.rename_matches(matches)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(box self.rename(*expr), FromVec::from_vec(a))
            }
            IfElse(pred, if_true, if_false) => {
                IfElse(box self.rename(*pred),
                       box self.rename(*if_true),
                       box self.rename(*if_false))
            }
            Do(bindings, expr) => {
                let bs: Vec<DoBinding<Name>> = bindings.move_iter().map(|bind| {
                    match bind {
                        DoExpr(expr) => DoExpr(self.rename(expr)),
                        DoLet(bs) => DoLet(self.rename_bindings(bs, false)),
                        DoBind(pattern, expr) => {
                            let Located { location: location, node: node } = pattern;
                            let loc = Located { location: location, node: self.rename_pattern(node) };
                            DoBind(loc, self.rename(expr))
                        }
                    }
                }).collect();
                Do(FromVec::from_vec(bs), box self.rename(*expr))
            }
            TypeSig(expr, sig) => {
                TypeSig(box self.rename(*expr), sig)
            }
            Paren(expr) => Paren(box self.rename(*expr))
        };
        let mut t = TypedExpr::with_location(e, location);
        t.typ = typ;
        t
    }

    fn rename_pattern(&mut self, pattern: Pattern<InternedStr>) -> Pattern<Name> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2: Vec<Pattern<Name>> = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(Name { name: s, uid: 0}, FromVec::from_vec(ps2))
            }
            IdentifierPattern(s) => IdentifierPattern(self.make_unique(s)),
            WildCardPattern => WildCardPattern
        }
    }
    ///Turns the string into the Name which is currently in scope
    ///If the name was not found it is assumed to be global
    fn get_name(&self, s: InternedStr) -> Name {
        match self.uniques.find(&s) {
            Some(&Name { uid: uid, .. }) => Name { name: s, uid: uid },
            None => Name { name: s, uid: 0 }//If the variable is not found in variables it is a global variable
        }
    }

    fn rename_matches(&mut self, matches: Match<InternedStr>) -> Match<Name> {
        match matches {
            Simple(e) => Simple(self.rename(e)),
            Guards(gs) => Guards(FromVec::<Guard<Name>>::from_vec(
                gs.move_iter()
                .map(|Guard { predicate: p, expression: e }|
                      Guard { predicate: self.rename(p), expression: self.rename(e) }
                )
                .collect()))
        }
    }

    fn rename_arguments(&mut self, arguments: ~[Pattern<InternedStr>]) -> ~[Pattern<Name>] {
        FromVec::<Pattern<Name>>::from_vec(arguments.move_iter().map(|a| self.rename_pattern(a)).collect())
    }

    ///Introduces a new Name to the current scope.
    ///If the name was already declared in the current scope an error is added
    fn make_unique(&mut self, name: InternedStr) -> Name {
        if self.uniques.in_current_scope(&name) {
            self.errors.insert(format!("{} is defined multiple times", name));
            self.uniques.find(&name).map(|x| x.clone()).unwrap()
        }
        else {
            let u = self.name_supply.from_interned(name.clone());
            self.uniques.insert(name, u.clone());
            u
        }
    }
}

pub fn rename_expr(expr: TypedExpr<InternedStr>) -> TypedExpr<Name> {
    let mut renamer = Renamer::new();
    renamer.rename(expr)
}

pub fn rename_module(module: Module<InternedStr>) -> Module<Name> {
    let mut renamer = Renamer::new();
    rename_module_(&mut renamer, module)
}
pub fn rename_module_(renamer: &mut Renamer, module: Module<InternedStr>) -> Module<Name> {
    let Module {
        name: name,
        imports: imports,
        classes : classes,
        dataDefinitions: data_definitions,
        newtypes: newtypes,
        typeDeclarations: typeDeclarations,
        bindings : bindings,
        instances: instances,
        fixity_declarations: fixity_declarations
    } = module;

    let data_definitions2 : Vec<DataDefinition<Name>> = data_definitions.move_iter().map(|data| {
        let DataDefinition {
            constructors : ctors,
            typ : typ,
            parameters : parameters,
            deriving
        } = data;
        let c: Vec<Constructor<Name>> = ctors.move_iter().map(|ctor| {
            let Constructor {
                name : name,
                typ : typ,
                tag : tag,
                arity : arity
            } = ctor;
            Constructor {
                name : Name { name: name, uid: 0 },
                typ : typ,
                tag : tag,
                arity : arity
            }
        }).collect();

        let d: Vec<Name> = deriving.move_iter().map(|s| {
            Name { name: s, uid: 0 }
        }).collect();

        DataDefinition {
            typ : typ,
            parameters : parameters,
            constructors : FromVec::from_vec(c),
            deriving : FromVec::from_vec(d)
        }
    }).collect();

    let newtypes2: Vec<Newtype<Name>> = newtypes.move_iter().map(|newtype| {
        let Newtype { typ: typ, constructor_type: constructor_type, deriving: deriving } = newtype;
        let deriving2: Vec<Name> = deriving.move_iter().map(|s| {
            Name { name: s, uid: 0 }
        }).collect();
        Newtype { typ: typ, constructor_type: constructor_type, deriving: FromVec::from_vec(deriving2) }
    }).collect();

    let instances2: Vec<Instance<Name>> = instances.move_iter().map(|instance| {
        let Instance {
            bindings : bindings,
            constraints : constraints,
            typ : typ,
            classname : classname
        } = instance;
        Instance {
            bindings : renamer.rename_bindings(bindings, true),
            constraints : constraints,
            typ : typ,
            classname : classname
        }
    }).collect();

    let classes2 : Vec<Class<Name>> = classes.move_iter().map(|class| {
        let Class {
            constraints: cs,
            name : name,
            variable : var,
            declarations : decls,
            bindings: bindings
        } = class;
        Class {
            constraints: cs,
            name: name,
            variable: var,
            declarations: decls,
            bindings: renamer.rename_bindings(bindings, true)
        }
    }).collect();

    let bindings2 = renamer.rename_bindings(bindings, true);

    let fixity_declarations2: Vec<FixityDeclaration<Name>> = fixity_declarations.move_iter()
        .map(|FixityDeclaration { assoc: assoc, precedence: precedence, operators: operators }| {

            let ops: Vec<Name> = operators.move_iter()
                .map(|s| renamer.get_name(s))
                .collect();
            FixityDeclaration { assoc: assoc, precedence: precedence,
                operators: FromVec::from_vec(ops)
            }
        })
        .collect();

    Module {
        name: renamer.make_unique(name),
        imports: imports,
        classes : FromVec::from_vec(classes2),
        dataDefinitions: FromVec::from_vec(data_definitions2),
        typeDeclarations: typeDeclarations,
        bindings : bindings2,
        instances: FromVec::from_vec(instances2),
        newtypes: FromVec::from_vec(newtypes2),
        fixity_declarations: FromVec::from_vec(fixity_declarations2)
    }
}

///Renames a vector of modules.
///If any errors are encounterd while renaming, an error message is output and fail is called
pub fn rename_modules(modules: Vec<Module<InternedStr>>) -> Vec<Module<Name>> {
    let mut renamer = Renamer::new();
    let ms = modules.move_iter().map(|module| {
        rename_module_(&mut renamer, module)
    }).collect();
    if renamer.errors.has_errors() {
        renamer.errors.report_errors("Renamer");
        fail!();
    }
    ms
}

#[cfg(test)]
mod tests {
    use renamer::*;
    use parser::*;
    #[test]
    #[should_fail]
    fn duplicate_binding() {
        let mut parser = Parser::new(
r"main = 1
test = []
main = 2".chars());
        let module = parser.module();
        rename_modules(vec!(module));
    }
}
<|endoftext|>


<commit_before><commit_msg>micro_http: update unit test<commit_after><|endoftext|>