/**
 * 
 */
package dspl.intermediate.instructions;

import dspl.intermediate.variable.Variable;

/**
 * Basic Abstract class for all other Abstract classes which 
 * represent the various kinds of 3-operand intermediary 
 * instructions generated from the AST
 * 
 * @author David
 */
public abstract class Instruction {
	/**
	 * The next instruction to be executed after this one
	 * Note in the case of branches, this is the next instruction
	 * to be executed after all of the instructions in a particular
	 * path of the branch are executed.
	 */
	public Instruction nextInstruction;
	
	/**
	 * The previous instruction executed, or in the case of the instruction following an if { } else { } block,
	 * it would refer to the BranchInstruction, rather than the previous instruction actually executed. 
	 */
	public Instruction prevInstruction; 
	
	/**
	 * Valid only in the first instruction (head of the list), the lastInstruction points to the 
	 * Instruction at the end of the list
	 */
	public Instruction lastInstruction;
	
	/**
	 * Contains an integer representing the the instruction type, referring to one of the
	 * instruction types listed below. 
	 * By default it is -1 so that it can be error checked to make sure that it has 
	 * actualy been assigned a valid value (starting @ 0) from the choice of valid
	 * instruction types
	 */
	//protected int instructionType = -1; 
	
	/*
	 * Enumeration types used to differentiate the types of instructions
	 */
	/**
	 * type for BranchInstruction
	 */
	public final static int INST_TYPE_BRANCH = 0; 
	
	/**
	 * type for ArithmaticInstruction
	 */
	public final static int INST_TYPE_ARITHMATIC = 1; 
	
	/**
	 * type for CCallInstruction
	 */
	public final static int INST_TYPE_CCALL = 2; 
	
	/**
	 * type for LoopInstruction
	 */
	public final static int INST_TYPE_FORLOOP = 3; 
	
	/**
	 * 
	 * @return the instruction type of this instruction
	 */
	public abstract int getInstType(); /* { 
		if (instructionType==-1) { 
			throw new Error("Error: instruction type is not defined"); 
		}
		return instructionType; 
	}*/
	
	
	/**
	 * Designed to be a recursive call to see if a given variable is used anymore 
	 * within a code block, after the current instruction. 
	 * Intention is to allow a way to parse the Instruction tree to see if a 
	 * specific variable is used again. 
	 * NOTE: may not be necessary, or may need to be augmented to return a value
	 * indicating how far away from the current instruction will it be used again 
	 * if desire to perform better register allocation. 
	 * @param v the variable to search for to see if it is used
	 * @return
	 */
	public abstract boolean usesVariable(Variable v); 
	
	public void setNextInstruction(Instruction next) { 
		if (next==null) { 
			throw new Error("Error: setNextInstruction passed a null instruction"); 
		}
		this.nextInstruction = next;
		next.prevInstruction = this; 
	}
}
