/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.sysml.parser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.sysml.api.DMLScript;
import org.apache.sysml.conf.DMLConfig;
import org.apache.sysml.lops.LopProperties;
import org.apache.sysml.lops.Lop;
import org.apache.sysml.lops.LopsException;
import org.apache.sysml.lops.compile.Dag;
import org.apache.sysml.parser.Expression.DataType;
import org.apache.sysml.runtime.DMLRuntimeException;
import org.apache.sysml.runtime.controlprogram.ExternalFunctionProgramBlock;
import org.apache.sysml.runtime.controlprogram.ExternalFunctionProgramBlockCP;
import org.apache.sysml.runtime.controlprogram.ForProgramBlock;
import org.apache.sysml.runtime.controlprogram.FunctionProgramBlock;
import org.apache.sysml.runtime.controlprogram.IfProgramBlock;
import org.apache.sysml.runtime.controlprogram.ParForProgramBlock;
import org.apache.sysml.runtime.controlprogram.Program;
import org.apache.sysml.runtime.controlprogram.ProgramBlock;
import org.apache.sysml.runtime.controlprogram.WhileProgramBlock;
import org.apache.sysml.runtime.controlprogram.parfor.ProgramConverter;
import org.apache.sysml.runtime.instructions.CPInstructionParser;
import org.apache.sysml.runtime.instructions.Instruction;


public class DMLProgram 
{
	
	private ArrayList<StatementBlock> _blocks;
	private HashMap<String, FunctionStatementBlock> _functionBlocks;
	private HashMap<String,DMLProgram> _namespaces;
	public static String DEFAULT_NAMESPACE = ".defaultNS";
	public static String INTERNAL_NAMESPACE = "_internal"; // used for multi-return builtin functions
	private static final Log LOG = LogFactory.getLog(DMLProgram.class.getName());
	
	public DMLProgram(){
		_blocks = new ArrayList<StatementBlock>();
		_functionBlocks = new HashMap<String,FunctionStatementBlock>();
		_namespaces = new HashMap<String,DMLProgram>();
	}
	
	public HashMap<String,DMLProgram> getNamespaces(){
		return _namespaces;
	}
	
	public void addStatementBlock(StatementBlock b, int pos) {
		_blocks.add(pos,b) ;
	}
	
	public void addStatementBlock(StatementBlock b){
		_blocks.add(b);
	}
	
	public int getNumStatementBlocks(){
		return _blocks.size();
	}

	/**
	 * 
	 * @param fkey   function key as concatenation of namespace and function name 
	 *               (see DMLProgram.constructFunctionKey)
	 * @return
	 */
	public FunctionStatementBlock getFunctionStatementBlock(String fkey) {
		String[] tmp = splitFunctionKey(fkey);
		return getFunctionStatementBlock(tmp[0], tmp[1]);
	}
	
	public FunctionStatementBlock getFunctionStatementBlock(String namespaceKey, String functionName) {
		DMLProgram namespaceProgram = this.getNamespaces().get(namespaceKey);
		if (namespaceProgram == null)
			return null;
	
		// for the namespace DMLProgram, get the specified function (if exists) in its current namespace
		FunctionStatementBlock retVal = namespaceProgram._functionBlocks.get(functionName);
		return retVal;
	}
	
	public HashMap<String, FunctionStatementBlock> getFunctionStatementBlocks(String namespaceKey) throws LanguageException{
		DMLProgram namespaceProgram = this.getNamespaces().get(namespaceKey);
		if (namespaceProgram == null){
			LOG.error("ERROR: namespace " + namespaceKey + " is undefined");
			throw new LanguageException("ERROR: namespace " + namespaceKey + " is undefined");
		}
		// for the namespace DMLProgram, get the functions in its current namespace
		return namespaceProgram._functionBlocks;
	}
	
	public ArrayList<FunctionStatementBlock> getFunctionStatementBlocks() 
		throws LanguageException
	{
		ArrayList<FunctionStatementBlock> ret = new ArrayList<FunctionStatementBlock>();
		
		for( DMLProgram nsProg : _namespaces.values() )
			ret.addAll(nsProg._functionBlocks.values());
		
		return ret;
	}

	public void addFunctionStatementBlock( String namespace, String fname, FunctionStatementBlock fsb ) 
		throws LanguageException
	{
		DMLProgram namespaceProgram = this.getNamespaces().get(namespace);
		if (namespaceProgram == null)
			throw new LanguageException( "Namespace does not exist." );
		
		namespaceProgram._functionBlocks.put(fname, fsb);
	}
	
	public ArrayList<StatementBlock> getStatementBlocks(){
		return _blocks;
	}
	
	public void setStatementBlocks(ArrayList<StatementBlock> passed){
		_blocks = passed;
	}
	
	public StatementBlock getStatementBlock(int i){
		return _blocks.get(i);
	}
	
	public void setStatementBlock(int i, StatementBlock sb) {
		 _blocks.set(i, sb);
	}

	public void mergeStatementBlocks(){
		_blocks = StatementBlock.mergeStatementBlocks(_blocks);
	}
	
	public String toString(){
		StringBuilder sb = new StringBuilder();
		
		// for each namespace, display all functions
		for (String namespaceKey : this.getNamespaces().keySet()){
			
			sb.append("NAMESPACE = " + namespaceKey + "\n");
			DMLProgram namespaceProg = this.getNamespaces().get(namespaceKey);
			
			
			sb.append("FUNCTIONS = ");
			
			for (FunctionStatementBlock fsb : namespaceProg._functionBlocks.values()){
				sb.append(fsb);
				sb.append(", ");
			}
			sb.append("\n");
			sb.append("********************************** \n");
		
		}
		
		sb.append("******** MAIN SCRIPT BODY ******** \n");
		for (StatementBlock b : _blocks){
			sb.append(b);
			sb.append("\n");
		}
		sb.append("********************************** \n");
		return sb.toString();
	}
	
	
	public Program getRuntimeProgram(DMLConfig config) throws IOException, LanguageException, DMLRuntimeException, LopsException {
		
		// constructor resets the set of registered functions
		Program rtprog = new Program();
		
		// for all namespaces, translate function statement blocks into function program blocks
		for (String namespace : _namespaces.keySet()){
		
			for (String fname : getFunctionStatementBlocks(namespace).keySet()){
				// add program block to program
				FunctionStatementBlock fsb = getFunctionStatementBlocks(namespace).get(fname);
				FunctionProgramBlock rtpb = (FunctionProgramBlock)createRuntimeProgramBlock(rtprog, fsb, config);
				rtprog.addFunctionProgramBlock(namespace, fname, rtpb);
				rtpb.setRecompileOnce( fsb.isRecompileOnce() );
			}
		}
		
		// for each top-level block
		for (StatementBlock sb : _blocks) {
		
			// add program block to program
			ProgramBlock rtpb = createRuntimeProgramBlock(rtprog, sb, config);
			rtprog.addProgramBlock(rtpb);
		}
		
		
		return rtprog ;
	}
	
	/**
	 * 
	 * @param prog
	 * @param sb
	 * @param config
	 * @return
	 * @throws IOException
	 * @throws LopsException
	 * @throws DMLRuntimeException
	 */
	public ProgramBlock createRuntimeProgramBlock(Program prog, StatementBlock sb, DMLConfig config) 
		throws IOException, LopsException, DMLRuntimeException 
	{
		Dag<Lop> dag = null; 
		Dag<Lop> pred_dag = null;

		ArrayList<Instruction> instruct;
		ArrayList<Instruction> pred_instruct = null;
		
		ProgramBlock retPB = null;
		
		// process While Statement - add runtime program blocks to program
		if (sb instanceof WhileStatementBlock){
		
			// create DAG for loop predicates
			pred_dag = new Dag<Lop>();
			((WhileStatementBlock) sb).get_predicateLops().addToDag(pred_dag);
			
			// create instructions for loop predicates
			pred_instruct = new ArrayList<Instruction>();
			ArrayList<Instruction> pInst = pred_dag.getJobs(null, config);
			for (Instruction i : pInst ) {
				pred_instruct.add(i);
			}
			
			// create while program block
			WhileProgramBlock rtpb = new WhileProgramBlock(prog, pred_instruct);
			
			if (rtpb.getPredicateResultVar() == null) {
				// e.g case : WHILE(continue)
				if ( ((WhileStatementBlock) sb).get_predicateLops().getExecLocation() == LopProperties.ExecLocation.Data ) {
					String resultVar = ((WhileStatementBlock) sb).get_predicateLops().getOutputParameters().getLabel();
					rtpb.setPredicateResultVar( resultVar );
				}
				else {
					LOG.error(sb.printBlockErrorLocation() + "Error in translating the WHILE predicate."); 
					throw new LopsException(sb.printBlockErrorLocation() + "Error in translating the WHILE predicate."); 
			
				}
			}			
			//// process the body of the while statement block ////
			
			WhileStatementBlock wsb = (WhileStatementBlock)sb;
			if (wsb.getNumStatements() > 1){
				LOG.error(wsb.printBlockErrorLocation() + "WhileStatementBlock should only have 1 statement");
				throw new LopsException(wsb.printBlockErrorLocation() + "WhileStatementBlock should only have 1 statement");
			}
			WhileStatement wstmt = (WhileStatement)wsb.getStatement(0);
			for (StatementBlock sblock : wstmt.getBody()){
				
				// process the body
				ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
				rtpb.addProgramBlock(childBlock);
			}
			
			// check there are actually Lops in to process (loop stmt body will not have any)
			if (wsb.getLops() != null && !wsb.getLops().isEmpty() ){
				LOG.error(wsb.printBlockErrorLocation() + "WhileStatementBlock should have no Lops");
				throw new LopsException(wsb.printBlockErrorLocation() + "WhileStatementBlock should have no Lops");
			}
			
			
			retPB = rtpb;
			
			//post processing for generating missing instructions
			//retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
			
			// add statement block
			retPB.setStatementBlock(sb);
			
			// add location information
			retPB.setAllPositions(sb.getBeginLine(), sb.getBeginColumn(), sb.getEndLine(), sb.getEndColumn());
		}
		
		// process If Statement - add runtime program blocks to program
		else if (sb instanceof IfStatementBlock){
		
			// create DAG for loop predicates
			pred_dag = new Dag<Lop>();
			((IfStatementBlock) sb).get_predicateLops().addToDag(pred_dag);
			
			// create instructions for loop predicates
			pred_instruct = new ArrayList<Instruction>();
			ArrayList<Instruction> pInst = pred_dag.getJobs(null, config);
			for (Instruction i : pInst ) {
				pred_instruct.add(i);
			}
			
			// create if program block
			IfProgramBlock rtpb = new IfProgramBlock(prog, pred_instruct);
			
			if (rtpb.getPredicateResultVar() == null ) {
				// e.g case : If(continue)
				if ( ((IfStatementBlock) sb).get_predicateLops().getExecLocation() == LopProperties.ExecLocation.Data ) {
					String resultVar = ((IfStatementBlock) sb).get_predicateLops().getOutputParameters().getLabel();
					rtpb.setPredicateResultVar( resultVar );
				}
				else {
					LOG.error(sb.printBlockErrorLocation() + "Error in translating the IF predicate."); 
					throw new LopsException(sb.printBlockErrorLocation() + "Error in translating the IF predicate."); 
				}
			}
			
			// process the body of the if statement block
			IfStatementBlock isb = (IfStatementBlock)sb;
			if (isb.getNumStatements() > 1){
				LOG.error(isb.printBlockErrorLocation() + "IfStatementBlock should have only 1 statement");
				throw new LopsException(isb.printBlockErrorLocation() + "IfStatementBlock should have only 1 statement");
			}
			IfStatement istmt = (IfStatement)isb.getStatement(0);
			
			// process the if body
			for (StatementBlock sblock : istmt.getIfBody()){
				ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
				rtpb.addProgramBlockIfBody(childBlock);
			}
			
			// process the else body
			for (StatementBlock sblock : istmt.getElseBody()){
				ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
				rtpb.addProgramBlockElseBody(childBlock); 
			}
			
			// check there are actually Lops in to process (loop stmt body will not have any)
			if (isb.getLops() != null && !isb.getLops().isEmpty() ){
				LOG.error(isb.printBlockErrorLocation() + "IfStatementBlock should have no Lops");
				throw new LopsException(isb.printBlockErrorLocation() + "IfStatementBlock should have no Lops");
			}
			
			retPB = rtpb;
			
			//post processing for generating missing instructions
			//retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
			
			// add statement block
			retPB.setStatementBlock(sb);
			
			// add location information
			retPB.setAllPositions(sb.getBeginLine(), sb.getBeginColumn(), sb.getEndLine(), sb.getEndColumn());
		}
		
		// process For Statement - add runtime program blocks to program
		// NOTE: applies to ForStatementBlock and ParForStatementBlock
		else if (sb instanceof ForStatementBlock) 
		{ 
			ForStatementBlock fsb = (ForStatementBlock) sb;
			
			// create DAGs for loop predicates 
			Dag<Lop> fromDag = new Dag<Lop>();
			Dag<Lop> toDag = new Dag<Lop>();
			Dag<Lop> incrementDag = new Dag<Lop>();
			if( fsb.getFromHops()!=null )
				fsb.getFromLops().addToDag(fromDag);
			if( fsb.getToHops()!=null )
				fsb.getToLops().addToDag(toDag);		
			if( fsb.getIncrementHops()!=null )
				fsb.getIncrementLops().addToDag(incrementDag);		
				
			// create instructions for loop predicates			
			ArrayList<Instruction> fromInstructions = fromDag.getJobs(null, config);
			ArrayList<Instruction> toInstructions = toDag.getJobs(null, config);
			ArrayList<Instruction> incrementInstructions = incrementDag.getJobs(null, config);		

			// create for program block
			String sbName = null;
			ForProgramBlock rtpb = null;
			IterablePredicate iterPred = fsb.getIterPredicate();
			String [] iterPredData= IterablePredicate.createIterablePredicateVariables(iterPred.getIterVar().getName(),
					                                                                   fsb.getFromLops(), fsb.getToLops(), fsb.getIncrementLops()); 
			
			if( sb instanceof ParForStatementBlock )
			{
				sbName = "ParForStatementBlock";
				rtpb = new ParForProgramBlock(prog, iterPredData,iterPred.getParForParams());
				ParForProgramBlock pfrtpb = (ParForProgramBlock)rtpb;
				pfrtpb.setResultVariables( ((ParForStatementBlock)sb).getResultVariables() );
				pfrtpb.setStatementBlock((ParForStatementBlock)sb); //used for optimization and creating unscoped variables
			}
			else //ForStatementBlock
			{
				sbName = "ForStatementBlock";
				rtpb = new ForProgramBlock(prog, iterPredData);
			}
			 
			rtpb.setFromInstructions(      fromInstructions      );
			rtpb.setToInstructions(        toInstructions        );
			rtpb.setIncrementInstructions( incrementInstructions );
			
			rtpb.setIterablePredicateVars( iterPredData );
			
			// process the body of the for statement block
			if (fsb.getNumStatements() > 1){
				LOG.error(fsb.printBlockErrorLocation() + " "  + sbName + " should have 1 statement" );
				throw new LopsException(fsb.printBlockErrorLocation() + " "  + sbName + " should have 1 statement" );
			}
			ForStatement fs = (ForStatement)fsb.getStatement(0);
			for (StatementBlock sblock : fs.getBody()){
				ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
				rtpb.addProgramBlock(childBlock); 
			}
		
			// check there are actually Lops in to process (loop stmt body will not have any)
			if (fsb.getLops() != null && !fsb.getLops().isEmpty()){
				LOG.error(fsb.printBlockErrorLocation() + sbName + " should have no Lops" );
				throw new LopsException(fsb.printBlockErrorLocation() + sbName + " should have no Lops" );
			}
			
			retPB = rtpb;
			
			//post processing for generating missing instructions
			//retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
			
			// add statement block
			retPB.setStatementBlock(sb);
			
			// add location information
			retPB.setAllPositions(sb.getBeginLine(), sb.getBeginColumn(), sb.getEndLine(), sb.getEndColumn());
		}
		
		// process function statement block - add runtime program blocks to program
		else if (sb instanceof FunctionStatementBlock){
			
			FunctionStatementBlock fsb = (FunctionStatementBlock)sb;
			if (fsb.getNumStatements() > 1){
				LOG.error(fsb.printBlockErrorLocation() + "FunctionStatementBlock should only have 1 statement");
				throw new LopsException(fsb.printBlockErrorLocation() + "FunctionStatementBlock should only have 1 statement");
			}
			FunctionStatement fstmt = (FunctionStatement)fsb.getStatement(0);
			FunctionProgramBlock rtpb = null;
			
			if (fstmt instanceof ExternalFunctionStatement) {
				 // create external function program block
				
				String execType = ((ExternalFunctionStatement) fstmt)
                				    .getOtherParams().get(ExternalFunctionStatement.EXEC_TYPE);
				boolean isCP = (execType.equals(ExternalFunctionStatement.IN_MEMORY)) ? true : false;
				
				String scratchSpaceLoc = null;
				try {
					scratchSpaceLoc = config.getTextValue(DMLConfig.SCRATCH_SPACE);
				} catch (Exception e){
					LOG.error(fsb.printBlockErrorLocation() + "could not retrieve parameter " + DMLConfig.SCRATCH_SPACE + " from DMLConfig");
				}				
				StringBuilder buff = new StringBuilder();
				buff.append(scratchSpaceLoc);
				buff.append(Lop.FILE_SEPARATOR);
				buff.append(Lop.PROCESS_PREFIX);
				buff.append(DMLScript.getUUID());
				buff.append(Lop.FILE_SEPARATOR);
				buff.append(ProgramConverter.CP_ROOT_THREAD_ID);
				buff.append(Lop.FILE_SEPARATOR);
				buff.append("PackageSupport");
				buff.append(Lop.FILE_SEPARATOR);
				String basedir =  buff.toString();
				
				if( isCP )
				{
					
					rtpb = new ExternalFunctionProgramBlockCP(prog, 
									fstmt.getInputParams(), fstmt.getOutputParams(), 
									((ExternalFunctionStatement) fstmt).getOtherParams(),
									basedir );					
				}
				else
				{
					rtpb = new ExternalFunctionProgramBlock(prog, 
									fstmt.getInputParams(), fstmt.getOutputParams(), 
									((ExternalFunctionStatement) fstmt).getOtherParams(),
									basedir);
				}
				
				if (!fstmt.getBody().isEmpty()){
					LOG.error(fstmt.printErrorLocation() + "ExternalFunctionStatementBlock should have no statement blocks in body");
					throw new LopsException(fstmt.printErrorLocation() + "ExternalFunctionStatementBlock should have no statement blocks in body");
				}
			}
			else 
			{
				// create function program block
				rtpb = new FunctionProgramBlock(prog, fstmt.getInputParams(), fstmt.getOutputParams());
				
				// process the function statement body
				for (StatementBlock sblock : fstmt.getBody()){	
					// process the body
					ProgramBlock childBlock = createRuntimeProgramBlock(prog, sblock, config);
					rtpb.addProgramBlock(childBlock);
				}
			}
			
			// check there are actually Lops in to process (loop stmt body will not have any)
			if (fsb.getLops() != null && !fsb.getLops().isEmpty()){
				LOG.error(fsb.printBlockErrorLocation() + "FunctionStatementBlock should have no Lops");
				throw new LopsException(fsb.printBlockErrorLocation() + "FunctionStatementBlock should have no Lops");
			}
			
			retPB = rtpb;
			
			// add location information
			retPB.setAllPositions(sb.getBeginLine(), sb.getBeginColumn(), sb.getEndLine(), sb.getEndColumn());
		}
		else {
	
			// handle general case
			ProgramBlock rtpb = new ProgramBlock(prog);
		
			// DAGs for Lops
			dag = new Dag<Lop>();

			// check there are actually Lops in to process (loop stmt body will not have any)
			if (sb.getLops() != null && !sb.getLops().isEmpty()){
			
				for (Lop l : sb.getLops()) {
					l.addToDag(dag);
				}
				
				// Instructions for Lobs DAGs
				instruct = dag.getJobs(sb, config);
				rtpb.addInstructions(instruct);
			}
			
			/*// TODO: check with Doug
			// add instruction for a function call
			if (sb.getFunctionCallInst() != null){
				rtpb.addInstruction(sb.getFunctionCallInst());
			}*/
			
			retPB = rtpb;
			
			//post processing for generating missing instructions
			//retPB = verifyAndCorrectProgramBlock(sb.liveIn(), sb.liveOut(), sb._kill, retPB);
			
			// add statement block
			retPB.setStatementBlock(sb);
			
			// add location information
			retPB.setAllPositions(sb.getBeginLine(), sb.getBeginColumn(), sb.getEndLine(), sb.getEndColumn());
		}
		
		return retPB;
	}	
	
	/**
	 * Post processing of each created program block in order to adhere to livein/liveout
	 * (currently needed for cleanup (especially for caching) of intermediate results if the last datasink 
	 * is an external function because instructions of external functions are created outside hops/lops,
	 * e.g., X=..., Y=fun(X) and X is not used afterwards )
	 * 
	 * NOTES: 
	 * (1) Rule1: checking livein and liveout is sufficient because the last external function is in its own
	 * programblock anyway.
	 * (2) as we cannot efficiently distinguish if the problematic var is created by an external function
	 * or some other instruction, we generate RMVAR instructions although for vars created by non-CP
	 * external functions RMFILEVAR instructions are required. However, all remaining files in scratch_space
	 * are cleaned after execution anyway.
	 * (3) As an alternative to doing rule 2, we could also check for existing objects in createvar and function invocation
	 * (or generic at program block level) and remove objects of previous iterations accordingly (but objects of last iteration
	 * would still require separate cleanup).
	 * 
	 * TODO: MB: external function invocations should become hops/lops as well (see instruction gen in DMLTranslator), 
	 * (currently not possible at Hops/Lops level due the requirement of multiple outputs for functions) 
	 * TODO: MB: we should in general always leverage livein/liveout during hops/lops generation.
	 * TODO: MB: verify and correct can be removed once everything is integrated in hops/lops generation
	 * 
	 * @param in
	 * @param out
	 * @param pb
	 * @return
	 * @throws DMLRuntimeException 
	 */
	@SuppressWarnings("unused")
	private ProgramBlock verifyAndCorrectProgramBlock(VariableSet in, VariableSet out, VariableSet kill, ProgramBlock pb) 
		throws DMLRuntimeException
	{	
		//RULE 1: if in IN and not in OUT, then there should be an rmvar or rmfilevar inst
		//(currently required for specific cases of external functions)
		for( String varName : in.getVariableNames() )
			if( !out.containsVariable(varName) ) 
			{
				DataType dt = in.getVariable(varName).getDataType();
				if( !(dt==DataType.MATRIX || dt==DataType.UNKNOWN) )
					continue; //skip rm instructions for non-matrix objects
				
				boolean foundRMInst = rContainsRMInstruction(pb, varName);
				
				if( !foundRMInst )
				{
					//create RMVAR instruction and put it into the programblock
					Instruction inst = createCleanupInstruction(varName);
					
					inst.setLocation(in.getVariable(varName));
					
					addCleanupInstruction(pb, inst);

					LOG.trace("Adding instruction (r1) "+inst.toString());
				}		
			}

		//RULE 2: if in KILL and not in IN and not in OUT, then there should be an rmvar or rmfilevar inst
		//(currently required for specific cases of nested loops)
		for( String varName : kill.getVariableNames() )
			if( (!in.containsVariable(varName)) && (!out.containsVariable(varName)) ) 
			{
				DataType dt = kill.getVariable(varName).getDataType();
				if( !(dt==DataType.MATRIX || dt==DataType.UNKNOWN) )
					continue; //skip rm instructions for non-matrix objects
				
				boolean foundRMInst = rContainsRMInstruction(pb, varName);
				
				if( !foundRMInst )
				{
					//create RMVAR instruction and put it into the programblock
					Instruction inst = createCleanupInstruction(varName);
					
					inst.setLocation(kill.getVariable(varName));
					
					//System.out.println("add rvar rule2 "+inst.toString());
					addCleanupInstruction(pb, inst);
					
					LOG.trace("Adding instruction (r2) "+inst.toString());
				}		
			}
		
		return pb;
	}
	
	private Instruction createCleanupInstruction(String varName) 
		throws DMLRuntimeException
	{
		//(example "CP+Lops.OPERAND_DELIMITOR+rmvar+Lops.OPERAND_DELIMITOR+Var7")
		StringBuilder sb = new StringBuilder();
		sb.append("CP");
		sb.append(Lop.OPERAND_DELIMITOR);
		sb.append("rmvar");
		sb.append(Lop.OPERAND_DELIMITOR);
		sb.append(varName);
		String str = sb.toString();
		Instruction inst = CPInstructionParser.parseSingleInstruction( str );
		
		return inst;
	}
	
	/**
	 * Determines if the given program block includes a RMVAR or RMFILEVAR
	 * instruction for the given varName.
	 * 
	 * @param pb
	 * @param varName
	 * @return
	 */
	private boolean rContainsRMInstruction(ProgramBlock pb, String varName)
	{	
		if (pb instanceof WhileProgramBlock)
		{
			WhileProgramBlock tmp = (WhileProgramBlock)pb;	
			for( ProgramBlock c : tmp.getChildBlocks() )
				if( rContainsRMInstruction(c, varName) )
					return true;
		}
		else if (pb instanceof IfProgramBlock)
		{
			IfProgramBlock tmp = (IfProgramBlock)pb;	
			for( ProgramBlock c : tmp.getChildBlocksIfBody() )
				if( rContainsRMInstruction(c, varName) )
					return true;
			for( ProgramBlock c : tmp.getChildBlocksElseBody() )
				if( rContainsRMInstruction(c, varName) )
					return true;
		}
		else if (pb instanceof ForProgramBlock) //includes ParFORProgramBlock
		{ 
			ForProgramBlock tmp = (ForProgramBlock)pb;	
			for( ProgramBlock c : tmp.getChildBlocks() )
				if( rContainsRMInstruction(c, varName) )
					return true;
		}		
		else if (  pb instanceof FunctionProgramBlock ) //includes ExternalFunctionProgramBlock and ExternalFunctionProgramBlockCP)
		{
			//do nothing
		}
		else 
		{
			for( Instruction inst : pb.getInstructions() )
			{
				String instStr = inst.toString();
				if(   instStr.contains("rmfilevar"+Lop.OPERAND_DELIMITOR+varName)
				   || instStr.contains("rmvar"+Lop.OPERAND_DELIMITOR+varName)  )
				{
					return true;
				}
			}	
		}
		
		
		return false;
	}
	
	/**
	 * Adds the generated cleanup RMVAR instruction to the given program block.
	 * In case of generic (last-level) programblocks it is added to the end of 
	 * the list of instructions, while for complex program blocks it is added to
	 * the end of the list of exit instructions.
	 * 
	 * @param pb
	 * @param inst
	 * @throws DMLRuntimeException 
	 */
	private void addCleanupInstruction( ProgramBlock pb, Instruction inst ) 
		throws DMLRuntimeException
	{
		//System.out.println("Adding rm var instructions: "+inst.toString());
		
		if (pb instanceof WhileProgramBlock)
		{
			WhileProgramBlock wpb = (WhileProgramBlock)pb;
			ArrayList<ProgramBlock> childs = wpb.getChildBlocks();
			if( !childs.get(childs.size()-1).getInstructions().isEmpty() ) //generic last level pb
				childs.get(childs.size()-1).addInstruction(inst);
			else{
				ProgramBlock pbNew = new ProgramBlock(pb.getProgram());
				pbNew.addInstruction(inst);
				childs.add(pbNew); 
			}
		}
		else if (pb instanceof ForProgramBlock) //includes ParFORProgramBlock
		{
			ForProgramBlock wpb = (ForProgramBlock)pb;
			ArrayList<ProgramBlock> childs = wpb.getChildBlocks();
			if( !childs.get(childs.size()-1).getInstructions().isEmpty() ) //generic last level pb
				childs.get(childs.size()-1).addInstruction(inst);
			else{
				ProgramBlock pbNew = new ProgramBlock(pb.getProgram());
				pbNew.addInstruction(inst);
				childs.add(pbNew); 
			}
		}
		else if (pb instanceof IfProgramBlock)
			((IfProgramBlock)pb).addExitInstruction(inst);
		else if (   pb instanceof FunctionProgramBlock )  //includes ExternalFunctionProgramBlock and ExternalFunctionProgramBlockCP)
			; //do nothing
		else 
		{
			pb.addInstruction(inst); //add inst at end of pb	
		}
	}
	
	/**
	 * 
	 * @param fnamespace
	 * @param fname
	 * @return
	 */
	public static String constructFunctionKey(String fnamespace, String fname)
	{
		return fnamespace + Program.KEY_DELIM + fname;
	}
	
	/**
	 * 
	 * @param fkey
	 * @return
	 */
	public static String[] splitFunctionKey(String fkey)
	{
		return fkey.split(Program.KEY_DELIM);
	}
}

