// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module provides linkage between rustc::middle::graph and
//! libgraphviz traits, specialized to attaching borrowck analysis
//! data to rendered labels.

pub use self::Variant::*;

pub use rustc::cfg::graphviz::{Node, Edge};
use rustc::cfg::graphviz as cfg_dot;

use borrowck;
use borrowck::{BorrowckCtxt, LoanPath};
use dot;
use rustc::cfg::CFGIndex;
use dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
use std::rc::Rc;
use dot::IntoCow;

#[derive(Debug, Copy, Clone)]
pub enum Variant {
    Loans,
    Moves,
    Assigns,
}

impl Variant {
    pub fn short_name(&self) -> &'static str {
        match *self {
            Loans   => "loans",
            Moves   => "moves",
            Assigns => "assigns",
        }
    }
}

pub struct DataflowLabeller<'a, 'tcx: 'a> {
    pub inner: cfg_dot::LabelledCFG<'a, 'tcx>,
    pub variants: Vec<Variant>,
    pub borrowck_ctxt: &'a BorrowckCtxt<'a, 'tcx>,
    pub analysis_data: &'a borrowck::AnalysisData<'a, 'tcx>,
}

impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
    fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
        let id = n.1.data.id();
        debug!("dataflow_for({:?}, id={:?}) {:?}", e, id, self.variants);
        let mut sets = "".to_string();
        let mut seen_one = false;
        for &variant in &self.variants {
            if seen_one { sets.push_str(" "); } else { seen_one = true; }
            sets.push_str(variant.short_name());
            sets.push_str(": ");
            sets.push_str(&self.dataflow_for_variant(e, n, variant));
        }
        sets
    }

    fn dataflow_for_variant(&self, e: EntryOrExit, n: &Node, v: Variant) -> String {
        let cfgidx = n.0;
        match v {
            Loans   => self.dataflow_loans_for(e, cfgidx),
            Moves   => self.dataflow_moves_for(e, cfgidx),
            Assigns => self.dataflow_assigns_for(e, cfgidx),
        }
    }

    fn build_set<O:DataFlowOperator, F>(&self,
                                        e: EntryOrExit,
                                        cfgidx: CFGIndex,
                                        dfcx: &DataFlowContext<'a, 'tcx, O>,
                                        mut to_lp: F) -> String where
        F: FnMut(usize) -> Rc<LoanPath<'tcx>>,
    {
        let mut saw_some = false;
        let mut set = "{".to_string();
        dfcx.each_bit_for_node(e, cfgidx, |index| {
            let lp = to_lp(index);
            if saw_some {
                set.push_str(", ");
            }
            let loan_str = self.borrowck_ctxt.loan_path_to_string(&lp);
            set.push_str(&loan_str);
            saw_some = true;
            true
        });
        set.push_str("}");
        set
    }

    fn dataflow_loans_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
        let dfcx = &self.analysis_data.loans;
        let loan_index_to_path = |loan_index| {
            let all_loans = &self.analysis_data.all_loans;
            let l: &borrowck::Loan = &all_loans[loan_index];
            l.loan_path()
        };
        self.build_set(e, cfgidx, dfcx, loan_index_to_path)
    }

    fn dataflow_moves_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
        let dfcx = &self.analysis_data.move_data.dfcx_moves;
        let move_index_to_path = |move_index| {
            let move_data = &self.analysis_data.move_data.move_data;
            let moves = move_data.moves.borrow();
            let the_move: &borrowck::move_data::Move = &(*moves)[move_index];
            move_data.path_loan_path(the_move.path)
        };
        self.build_set(e, cfgidx, dfcx, move_index_to_path)
    }

    fn dataflow_assigns_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
        let dfcx = &self.analysis_data.move_data.dfcx_assign;
        let assign_index_to_path = |assign_index| {
            let move_data = &self.analysis_data.move_data.move_data;
            let assignments = move_data.var_assignments.borrow();
            let assignment: &borrowck::move_data::Assignment = &(*assignments)[assign_index];
            move_data.path_loan_path(assignment.path)
        };
        self.build_set(e, cfgidx, dfcx, assign_index_to_path)
    }
}

impl<'a, 'tcx> dot::Labeller<'a> for DataflowLabeller<'a, 'tcx> {
    type Node = Node<'a>;
    type Edge = Edge<'a>;
    fn graph_id(&'a self) -> dot::Id<'a> { self.inner.graph_id() }
    fn node_id(&'a self, n: &Node<'a>) -> dot::Id<'a> { self.inner.node_id(n) }
    fn node_label(&'a self, n: &Node<'a>) -> dot::LabelText<'a> {
        let prefix = self.dataflow_for(EntryOrExit::Entry, n);
        let suffix = self.dataflow_for(EntryOrExit::Exit, n);
        let inner_label = self.inner.node_label(n);
        inner_label
            .prefix_line(dot::LabelText::LabelStr(prefix.into_cow()))
            .suffix_line(dot::LabelText::LabelStr(suffix.into_cow()))
    }
    fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) }
}

impl<'a, 'tcx> dot::GraphWalk<'a> for DataflowLabeller<'a, 'tcx> {
    type Node = Node<'a>;
    type Edge = Edge<'a>;
    fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
    fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
    fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
    fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }
}
