package natlab.toolkits.analysis.liveliness;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ast.*;
import analysis.*;
import analysis.natlab.*;
import natlab.toolkits.analysis.*;
import natlab.toolkits.analysis.varorfun.VFDatum;
import natlab.toolkits.analysis.varorfun.ValueDatumPair;
import natlab.toolkits.utils.NodeFinder;

public class LivelinessAnalysis extends
		AbstractStructuralBackwardAnalysis<HashSetFlowSet<String>> implements FixedPointScriptAnalysis<HashSetFlowSet<String>> {

	public LivelinessAnalysis(ASTNode tree) {
		super(tree);	
	}	
	
	@Override
	public void caseStmt(Stmt s) {
		outFlowSets.put(s, currentOutSet.copy());
		caseASTNode(s);
		inFlowSets.put(s, currentOutSet.copy());

	}
	
	private NameExpr getLValue(Expr lv) {
		NameExpr ne = null;
		if (lv instanceof ParameterizedExpr)
			lv = ((ParameterizedExpr) lv).getTarget();
		if (lv instanceof CellIndexExpr)
			lv = ((CellIndexExpr) lv).getTarget();
		if (lv instanceof DotExpr)
			lv = ((DotExpr) lv).getTarget();
		if (lv instanceof CellIndexExpr)
			lv = ((CellIndexExpr) lv).getTarget();
		if (lv instanceof DotExpr)
			lv = ((DotExpr) lv).getTarget();
		if (lv instanceof NameExpr)
			ne = (NameExpr) lv;
		else{
			System.out.println("LValue target not found at "
					+ lv.getPrettyPrinted());
			return lv.getNameExpressions().iterator().next();
		}
		return ne;
	}
	public void caseNameExpr(NameExpr ne){
		currentOutSet.add(ne.getName().getID());
	}
	
	@Override
	public void caseAssignStmt(AssignStmt s) {
		outFlowSets.put(s, currentOutSet.copy());	
		Set<NameExpr> lValues = new HashSet<NameExpr>();
		List<NameExpr> all = NodeFinder.find(s, NameExpr.class);
		if (s.getLHS() instanceof MatrixExpr) {
			for (Expr expr : ((MatrixExpr) s.getLHS()).getRow(0)
					.getElementList()) {
				NameExpr ne = getLValue(expr);
				lValues.add(ne);
				currentOutSet.remove(ne.getName().getID());
			}
		} else
			lValues.add(getLValue(s.getLHS()));
		
//		System.out.println(s.getPrettyPrinted()+ " "+ lValues);
		for (NameExpr n : lValues)
			currentOutSet.remove(n.getName().getID());
		
		caseASTNode(s.getRHS());
		
		for (NameExpr n : all)
			if (!lValues.contains(n))
				currentOutSet.add(n.getName().getID());

		inFlowSets.put(s, currentOutSet.copy());

	}

	@Override
	public void caseFunction(Function node) {
		currentOutSet = newInitialFlow();
		currentInSet = currentOutSet;
		outFlowSets.put(node, currentOutSet);
		node.getStmts().analyze(this);
		inFlowSets.put(node, currentOutSet);

	}


	@Override
	public void caseScript(Script node) {
		currentOutSet = newInitialFlow();
		currentInSet = currentOutSet;
		outFlowSets.put(node, currentOutSet);
		node.getStmts().analyze(this);
		inFlowSets.put(node, currentOutSet);
	}

	

	public boolean isLive(ASTNode n, String s) {
		while (!(n instanceof Stmt)) {
			n = n.getParent();
		}
		if (inFlowSets.containsKey(n))
			return inFlowSets.get(n).contains(s);
		throw new RuntimeException("NameExpr not inside an Stmt");
	}

	@Override
	public void copy(HashSetFlowSet<String> source, HashSetFlowSet<String> dest) {
		dest.clear();
		dest.addAll(source);
	}

	@Override
	public void merge(HashSetFlowSet<String> in1, HashSetFlowSet<String> in2,
			HashSetFlowSet<String> out) {
		out.clear();
		out.addAll(in1);
		out.addAll(in2);		
	}

	@Override
	public HashSetFlowSet<String> newInitialFlow() {
		return new HashSetFlowSet<String>();
	}

	@Override
	public void setCurrentResults(Map<Script, HashSetFlowSet<String>> res) {
		// TODO Auto-generated method stub
		
	}
}

@@ -427,16 +427,22 @@
 bstractS
+impleS
 tructura
@@ -545,16 +545,16 @@
 ing%3E%3E %7B%0A
-
 %0A%09public
@@ -735,35 +735,34 @@
 s.put(s, current
-Out
+In
 Set.copy());%0A%0A%09%7D
@@ -1452,35 +1452,34 @@
 r ne)%7B%0A%09%09current
-Out
+In
 Set.add(ne.getNa
@@ -2278,35 +2278,34 @@
 s.put(s, current
-Out
+In
 Set.copy());%0A%0A%09%7D
@@ -2418,32 +2418,39 @@
  = currentOutSet
+.copy()
 ;%0A%09%09outFlowSets.
@@ -2534,27 +2534,26 @@
 ode, current
-Out
+In
 Set);%0A%0A%09%7D%0A%0A%0A
@@ -2668,16 +2668,23 @@
 ntOutSet
+.copy()
 ;%0A%09%09outF
@@ -2776,27 +2776,26 @@
 ode, current
-Out
+In
 Set);%0A%09%7D%0A%0A%09%0A
@@ -3136,42 +3136,24 @@
 %7B%0A%09%09
-dest.clear();%0A%09%09dest.addAll(source
+source.copy(dest
 );%0A%09
@@ -3280,60 +3280,28 @@
 %7B%0A%09%09
-out.clear();%0A%09%09out.addAll(in1);%0A%09%09out.addAll(in2);%09%09
+in1.union(in2, out);
 %0A%09%7D%0A

Fix LivelinessAnalysis#merge