//! Def-use analysis.

use rustc::mir::{Body, BodyCache, Local, Location, PlaceElem, ReadOnlyBodyCache, VarDebugInfo};
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc::ty::TyCtxt;
use rustc_index::vec::IndexVec;
use std::mem;

pub struct DefUseAnalysis {
    info: IndexVec<Local, Info>,
}

#[derive(Clone)]
pub struct Info {
    // FIXME(eddyb) use smallvec where possible.
    pub defs_and_uses: Vec<Use>,
    var_debug_info_indices: Vec<usize>,
}

#[derive(Clone)]
pub struct Use {
    pub context: PlaceContext,
    pub location: Location,
}

impl DefUseAnalysis {
    pub fn new(body: &Body<'_>) -> DefUseAnalysis {
        DefUseAnalysis {
            info: IndexVec::from_elem_n(Info::new(), body.local_decls.len()),
        }
    }

    pub fn analyze(&mut self, body: ReadOnlyBodyCache<'_, '_>) {
        self.clear();

        let mut finder = DefUseFinder {
            info: mem::take(&mut self.info),
            var_debug_info_index: 0,
            in_var_debug_info: false,
        };
        finder.visit_body(body);
        self.info = finder.info
    }

    fn clear(&mut self) {
        for info in &mut self.info {
            info.clear();
        }
    }

    pub fn local_info(&self, local: Local) -> &Info {
        &self.info[local]
    }

    fn mutate_defs_and_uses(
        &self,
        local: Local,
        body: &mut BodyCache<'tcx>,
        new_local: Local,
        tcx: TyCtxt<'tcx>,
    ) {
        let mut visitor = MutateUseVisitor::new(local, new_local, tcx);
        let info = &self.info[local];
        for place_use in &info.defs_and_uses {
            visitor.visit_location(body, place_use.location)
        }
        // Update debuginfo as well, alongside defs/uses.
        for &i in &info.var_debug_info_indices {
            visitor.visit_var_debug_info(&mut body.var_debug_info[i]);
        }
    }

    // FIXME(pcwalton): this should update the def-use chains.
    pub fn replace_all_defs_and_uses_with(&self,
                                          local: Local,
                                          body: &mut BodyCache<'tcx>,
                                          new_local: Local,
                                          tcx: TyCtxt<'tcx>) {
        self.mutate_defs_and_uses(local, body, new_local, tcx)
    }
}

struct DefUseFinder {
    info: IndexVec<Local, Info>,
    var_debug_info_index: usize,
    in_var_debug_info: bool,
}

impl Visitor<'_> for DefUseFinder {
    fn visit_local(&mut self,
                   &local: &Local,
                   context: PlaceContext,
                   location: Location) {
        let info = &mut self.info[local];
        if self.in_var_debug_info {
            info.var_debug_info_indices.push(self.var_debug_info_index);
        } else {
            info.defs_and_uses.push(Use {
                context,
                location,
            });
        }
    }
    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
        assert!(!self.in_var_debug_info);
        self.in_var_debug_info = true;
        self.super_var_debug_info(var_debug_info);
        self.in_var_debug_info = false;
        self.var_debug_info_index += 1;
    }
}

impl Info {
    fn new() -> Info {
        Info {
            defs_and_uses: vec![],
            var_debug_info_indices: vec![],
        }
    }

    fn clear(&mut self) {
        self.defs_and_uses.clear();
        self.var_debug_info_indices.clear();
    }

    pub fn def_count(&self) -> usize {
        self.defs_and_uses.iter().filter(|place_use| place_use.context.is_mutating_use()).count()
    }

    pub fn def_count_not_including_drop(&self) -> usize {
        self.defs_not_including_drop().count()
    }

    pub fn defs_not_including_drop(
        &self,
    ) -> impl Iterator<Item=&Use> {
        self.defs_and_uses.iter().filter(|place_use| {
            place_use.context.is_mutating_use() && !place_use.context.is_drop()
        })
    }

    pub fn use_count(&self) -> usize {
        self.defs_and_uses.iter().filter(|place_use| {
            place_use.context.is_nonmutating_use()
        }).count()
    }
}

struct MutateUseVisitor<'tcx> {
    query: Local,
    new_local: Local,
    tcx: TyCtxt<'tcx>,
}

impl MutateUseVisitor<'tcx> {
    fn new(
        query: Local,
        new_local: Local,
        tcx: TyCtxt<'tcx>,
    ) -> MutateUseVisitor<'tcx> {
        MutateUseVisitor { query, new_local, tcx }
    }
}

impl MutVisitor<'tcx> for MutateUseVisitor<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_local(&mut self,
                    local: &mut Local,
                    _context: PlaceContext,
                    _location: Location) {
        if *local == self.query {
            *local = self.new_local;
        }
    }

    fn process_projection_elem(
        &mut self,
        elem: &PlaceElem<'tcx>,
    ) -> Option<PlaceElem<'tcx>> {
        match elem {
            PlaceElem::Index(local) if *local == self.query => {
                Some(PlaceElem::Index(self.new_local))
            }
            _ => None,
        }
    }
}
