// $ANTLR : "DSPLAstWalker.g" -> "DSPLAstToIntermediateWalker.java"$
 
	package dspl.frontend;
	
	import dspl.intermediate.*;
	import dspl.intermediate.instructions.*;
	import dspl.intermediate.variable.*;
	import dspl.SymbolTable;
	import antlr.TreeParser;
	import antlr.collections.AST;
	import java.util.*;

import antlr.TreeParser;
import antlr.Token;
import antlr.collections.AST;
import antlr.RecognitionException;
import antlr.ANTLRException;
import antlr.NoViableAltException;
import antlr.MismatchedTokenException;
import antlr.SemanticException;
import antlr.collections.impl.BitSet;
import antlr.ASTPair;
import antlr.collections.impl.ASTArray;


/**
 * This class is the tree walker which walks the AST for a dspl file and produces an
 * intermediate representation.
 * @author Varun, Jeff, Mike, David
 */
public class DSPLAstToIntermediateWalker extends antlr.TreeParser       implements DSPLAstToIntermediateWalkerTokenTypes
 {

	InstructionSet iSet = new InstructionSet(); //This InstructionSet is the root set for the whole program
	SymbolTable table = new SymbolTable(); //This is the symbol table for our only scope
	int nextTempNumber = 0; //This is a counter to keep track of what number our next temporary variable should be
	int rightType = -1;
	boolean convert = false;
	int indexCount = 0;
	public SymbolTable getSymbolTable() { 
		return table; 	
	}
	
	
	/**
	 * Helper function intended to be used by expressions which require a temporary variable to store a result
	 * variableType must correspond to one of the Variable.DATATYPE_xxx (int/uint/float/etc)<br>
	 * 
	 * @author dlariviere, jcropsey
	 */
	protected Variable getTempAtomicVar(int variableType, String prepend) throws SemanticAnalysisException { 
		
		Variable tempValue;
		try
		{
		tempValue = Variable.getNewAtomic(Variable.getAntlrTypeFromVarType(variableType), prepend+"_temp"+(nextTempNumber++), 0, false);
		try{
		table.addVariable(tempValue);
				
		}
		catch(SymbolicException e)
		{
			tempValue = getTempAtomicVar(variableType, prepend+"_");
		}
		}
		catch(NumberFormatException e)
		{
			throw new SemanticAnalysisException(null, "Number too large for assignment");
		} 
		
		return tempValue;
	}
	
	/**
	* Series of helper functions for conversion analysis
	* @author JCropsey
	*/
	protected void incrementIndexCount()
	{
		indexCount++;
	}
	
	protected void decrementIndexCount()
	{
		indexCount--;	
	}
	
	protected boolean isIndex()
	{
		if(indexCount > 0)
			return true;
		return false;
	}
	
	protected void setConversion(int conversionType)
	{
		rightType =	conversionType;
		convert = true;
	}
	
	protected void disableConversion()
	{
		convert = false;
	}
	
	protected int findType(int dataType)
	{
		if(isIndex())
			return Variable.DATA_TYPE_INT;
		else if(convert)
			return rightType;
		else
			return dataType;
	}
	
	protected boolean needsConversion(int dataType)
	{	
		if((convert && dataType != rightType && !isIndex())) { //dlariviere - added !isIndex, also your converting based on past datatype and not 
			return true;
		}
		if (isIndex() && dataType != Variable.DATA_TYPE_INT) { 
			return true; 	
		}
		return false;	
	}
	
	/**
	*Function that creates a new Float "Constant" (since its stored in the symbol table)
	*@author JCropsey
	*/
	protected Variable newFloatConstant(String val) throws SemanticAnalysisException
	{
		try
		{
			Variable myReal = Variable.getNewAtomic(Variable.getAntlrTypeFromVarType(Variable.DATA_TYPE_FLOAT),table.getNextFloatConstID(), 1, false); 
			System.out.println("Created Real Var");
			myReal.setValue(val); //set the value of the variable to the floating poitn constant string. doing so should get it printed in .data by the AsmFileGen
			System.out.println("Set Variable Value to: " + myReal.getValue());
			try
			{
	 	 		table.addVariable(myReal);  // @author Dave, actually add the variable to the symbol table
	  			System.out.println("Adding to Real to the symbol table");
	  		} 
		  	catch(SymbolicException e)
		  	{ 
		  		throw new Error("Failed on adding floating point Constant to ST: " + e.getMessage());
	  		}
	  	
	  	//added dlariviere to ensure conversion
		  	if (needsConversion(myReal.getDataType())) 
		  	{ 
				Variable tempConvert; 
				tempConvert = getTempAtomicVar(findType(myReal.getDataType()), ""); //modified dlariviere - needed findType(), else it wasn't actually converting to the right type, but instead to itself
				iSet.append(new ArithmaticInstruction(ArithmaticInstruction.OPERATION_CONVERSION, myReal, null, tempConvert));
				myReal = tempConvert;
	  		}
	  		return myReal;
		}
		catch(NumberFormatException e)
		{
			throw new SemanticAnalysisException(null, "Number too large for assignment");
		}
	}
	
	/**
	*Functions that Assist in Semantic Anaylsis or Array operations
	*@author JCropsey
	*/
	
	protected int arraysize = 0;
	protected boolean arrayop = false;
	
	protected void setSize(int size)
	{
		arraysize = size;	
	}
	
	protected int getSize()
	{
		return arraysize;	
	}
	
	protected boolean validArrayOperation(int size)
	{
		if(size == arraysize)
			return true;
		return false;
	}
	
	protected void arrayOperationEnter()
	{
		arrayop = true;	
	}
	
	protected void arrayOperationExit()
	{
		arrayop = false;	
	}
	
	protected boolean isArrayOp()
	{
		return arrayop;	
	}
	
	/**
	*Functions to aid in Semantic checking of logical expressions
	*@author JCropsey
	*/
	protected int checkLogical(Variable e1, Variable e2, AST _t) throws SemanticAnalysisException
	{
		if(!(!e1.isConstant() && !e2.isConstant()) && !(e1.getDataType() == e2.getDataType()))
			if(e1.isConstant())
				return 1;
			else
				return 2;
		if(e1.getDataType() != e2.getDataType())
			throw new SemanticAnalysisException((DSPLAST) _t, "Arguments to a logical operation must be of the same type");
		if(e1.isArray() || e2.isArray())
			throw new SemanticAnalysisException((DSPLAST) _t, "Arguments to a logical operation	cannot be arrays");
		return 0;
		
	}
	
public DSPLAstToIntermediateWalker() {
	tokenNames = _tokenNames;
}

/**
 * The program rule is the one that...matches the whole program, represented by the root node
 * of the AST.
 * The program rule is the one that dsplc calls and so it must return the root instruction
 * set.
 *
 * When writing rules it is important to understand how they work.  ANTLR, when tree-walking
 * uses a syntax of:
 * variable=rule {java action}
 * only the rule is required, but it is possible, depending on what the rule return, to set
 * its return value to a variable, and also set some action that will be performed when the
 * the rule has been matched.  This action is performed *after* the rule is matched.
 */
	public final InstructionSet  program(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		InstructionSet set;
		
		AST program_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
			InstructionSet pset = null;
			pset = null;
		
			Instruction s;
			set = iSet; 
			try
			{
				table.constructTable(_t); //build the symbol table from the AST
			}
			catch(NumberFormatException e)
			{
				throw new SemanticAnalysisException(null, "Number too large for assignment");
			}
		
		
		try {      // for error handling
			AST __t617 = _t;
			AST tmp1_AST_in = (AST)_t;
			match(_t,PROGRAM);
			_t = _t.getFirstChild();
			{
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case DECLS:
			{
				decls(_t);
				_t = _retTree;
				break;
			}
			case 3:
			case LITERAL_if:
			case LITERAL_while:
			case LITERAL_for:
			case LITERAL_ccall:
			case ASSIGN:
			{
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
			}
			{
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case LITERAL_if:
			case LITERAL_while:
			case LITERAL_for:
			case LITERAL_ccall:
			case ASSIGN:
			{
				s=stmts(_t);
				_t = _retTree;
				break;
			}
			case 3:
			{
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
			}
			_t = __t617;
			_t = _t.getNextSibling();
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return set;
	}
	
/**
 * We construct the symbol table outside of the tree walker, so we don't actually do anything
 * for the declarations that we find here
 */
	public final void decls(AST _t) throws RecognitionException {
		
		AST decls_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
		
		
		try {      // for error handling
			AST __t621 = _t;
			AST tmp2_AST_in = (AST)_t;
			match(_t,DECLS);
			_t = _t.getFirstChild();
			{
			_loop623:
			do {
				if (_t==null) _t=ASTNULL;
				if ((_t.getType()==ID)) {
					AST tmp3_AST_in = (AST)_t;
					match(_t,ID);
					_t = _t.getNextSibling();
				}
				else {
					break _loop623;
				}
				
			} while (true);
			}
			_t = __t621;
			_t = _t.getNextSibling();
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
	}
	
/** stmts is simply a sequence of statments */
	public final Instruction  stmts(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		Instruction s;
		
		AST stmts_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		s = null; Instruction s1;
		
		try {      // for error handling
			s=stmt(_t);
			_t = _retTree;
			{
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case LITERAL_if:
			case LITERAL_while:
			case LITERAL_for:
			case LITERAL_ccall:
			case ASSIGN:
			{
				s1=stmts(_t);
				_t = _retTree;
				break;
			}
			case 3:
			case LBRACE:
			{
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
			}
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return s;
	}
	
/** a statements can be one of many types, and an appropriate instruction needs to be
 * appended to the current InstructionSet based on what needs to be done
 */
	public final Instruction  stmt(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		Instruction s;
		
		AST stmt_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		Variable e1, e2;
		s = null;
			Instruction s1, s2;
			Comparison sb;
			
		
		
		try {      // for error handling
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case ASSIGN:
			{
				AST __t627 = _t;
				AST tmp4_AST_in = (AST)_t;
				match(_t,ASSIGN);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				setConversion(e1.getDataType()); 
					if(e1.isArray()){arrayOperationEnter(); setSize(e1.getArraySize());}
				e2=expr(_t);
				_t = _retTree;
				
						disableConversion(); arrayOperationExit();
						
					System.out.println("ASSIGN Found");
						System.out.println("Going to add instruction.");
						//checking for pattern where temporary variable is created to store the results of an expression before assigning it to another variable
						//if pattern is matched, the expression is condensed into a single expression, with the actual destination being plugged in place of the temp
						//the only exception to this is when using elements whihc require temporary registers 
						if ((iSet.last() instanceof ArithmaticInstruction) &&  //if the last instruction added was an ArithmaticInst
							e2 == ((ArithmaticInstruction) iSet.last()).dest 	//and if the last instruction added was writing a value to e2
							&& !e1.isElement()) {								//and e1 is not an element Variable 
							
							((ArithmaticInstruction) iSet.last()).dest = e1;	//then instead of creating a new instruction, write the value of the last instruction to e1, instead of temp var
						}
						//else create a new instruction 
						else {
							s = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_ASSIGNMENT,
								e2,null,e1);
							iSet.append(s);			
						}
					
				_t = __t627;
				_t = _t.getNextSibling();
				break;
			}
			case LITERAL_ccall:
			{
				AST __t628 = _t;
				AST tmp5_AST_in = (AST)_t;
				match(_t,LITERAL_ccall);
				_t = _t.getFirstChild();
				System.out.println("Going to add ccall"); String functionName = null; Variable currentArg = null;
				functionName=ccallname(_t);
				_t = _retTree;
				s = new CCallInstruction(functionName);
				{
				_loop630:
				do {
					if (_t==null) _t=ASTNULL;
					if ((_tokenSet_0.member(_t.getType()))) {
						currentArg=expr(_t);
						_t = _retTree;
						((CCallInstruction) s).addParameter(currentArg);
					}
					else {
						break _loop630;
					}
					
				} while (true);
				}
				iSet.append(s);
				_t = __t628;
				_t = _t.getNextSibling();
				break;
			}
			case LITERAL_if:
			{
				AST __t631 = _t;
				AST tmp6_AST_in = (AST)_t;
				match(_t,LITERAL_if);
				_t = _t.getFirstChild();
				System.out.println("Going to add if"); s2 = null;
				sb=bool(_t);
				_t = _retTree;
				s1=subprog(_t);
				_t = _retTree;
				{
				if (_t==null) _t=ASTNULL;
				switch ( _t.getType()) {
				case LBRACE:
				{
					s2=subprog(_t);
					_t = _retTree;
					break;
				}
				case 3:
				{
					break;
				}
				default:
				{
					throw new NoViableAltException(_t);
				}
				}
				}
				
					 		Comparison sr = ((Comparison)sb);
					 		s = new BranchInstruction(new Comparison(sr.arg1, sr.arg2, sr.condition), s1, s2);
					 		iSet.append(s);
					 	
				_t = __t631;
				_t = _t.getNextSibling();
				break;
			}
			case LITERAL_for:
			{
				AST __t633 = _t;
				AST tmp7_AST_in = (AST)_t;
				match(_t,LITERAL_for);
				_t = _t.getFirstChild();
				System.out.println("Going to add for"); Instruction incrementInstruction;
				{
				_loop635:
				do {
					if (_t==null) _t=ASTNULL;
					if ((_tokenSet_1.member(_t.getType()))) {
						stmt(_t);
						_t = _retTree;
					}
					else {
						break _loop635;
					}
					
				} while (true);
				}
				InstructionSet superIset = iSet; iSet = new InstructionSet();
				sb=bool(_t);
				_t = _retTree;
				s1 = iSet.first(); iSet = new InstructionSet();
				incrementInstruction=stmts(_t);
				_t = _retTree;
				s1 = iSet.first(); iSet = superIset;
				s2=subprog(_t);
				_t = _retTree;
					s = new LoopInstruction(null, new Comparison(sb.arg1, sb.arg2, sb.condition), s1, s2);
						iSet.append(s);
				_t = __t633;
				_t = _t.getNextSibling();
				break;
			}
			case LITERAL_while:
			{
				AST __t636 = _t;
				AST tmp8_AST_in = (AST)_t;
				match(_t,LITERAL_while);
				_t = _t.getFirstChild();
				System.out.println("Going to add while");
				sb=bool(_t);
				_t = _retTree;
				s1=subprog(_t);
				_t = _retTree;
				
					 	Comparison sr = ((Comparison)sb);
					 	s = new LoopInstruction(null, new Comparison(sr.arg1, sr.arg2, sr.condition), null, s1);
					 	iSet.append(s);
					
				_t = __t636;
				_t = _t.getNextSibling();
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return s;
	}
	
	public final Variable  expr(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		Variable object;
		
		AST expr_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
			object = null;
			//For expressions that require some match, we must add the instruction to be performed
			//to the current instruction set.  Then we can just return the Variable the represents the
			//result.
			Instruction exprInstruct;
			System.out.println("Matching expr");
			
		
		
		try {      // for error handling
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case NEGATE:
			{
				AST __t649 = _t;
				AST tmp9_AST_in = (AST)_t;
				match(_t,NEGATE);
				_t = _t.getFirstChild();
				Variable negative; Variable myVar = null;
				negative=expr(_t);
				_t = _retTree;
					
					if(negative.getDataType() == Variable.DATA_TYPE_FLOAT)
					{
						System.out.println("Making Negative Real"); 
						myVar = newFloatConstant("-"+String.valueOf(negative.getValue()));
					}
					else if(negative.getDataType() != Variable.DATA_TYPE_FLOAT && negative.isConstant())
					{
						try
						{
							myVar = Variable.getNewAtomic(Variable.getAntlrTypeFromVarType(findType(0)), "-" + negative.getIdentifier(), 1, true);
						}
						catch(NumberFormatException e)
						{
							throw new SemanticAnalysisException(null, "Number too large for assignment");
						}
					}
					else
					{
						throw new SemanticAnalysisException((DSPLAST)_t, "Only constants can be negated");	
					}
					object = myVar;
				
				_t = __t649;
				_t = _t.getNextSibling();
				break;
			}
			case PLUS:
			{
				AST __t650 = _t;
				AST tmp10_AST_in = (AST)_t;
				match(_t,PLUS);
				_t = _t.getFirstChild();
				
						Variable arg1, arg2;
						System.out.println("Going to match PLUS args");
					
				arg1=expr(_t);
				_t = _retTree;
				arg2=expr(_t);
				_t = _retTree;
				
						object = getTempAtomicVar(findType(0), ""); //@author dlariviere - utilizes helper function instead of repeating the same code over and over
						exprInstruct = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_ADDITION, arg1, arg2, object);
						iSet.append(exprInstruct);
					
				_t = __t650;
				_t = _t.getNextSibling();
				break;
			}
			case MINUS:
			{
				AST __t651 = _t;
				AST tmp11_AST_in = (AST)_t;
				match(_t,MINUS);
				_t = _t.getFirstChild();
				
						Variable arg1, arg2;
						System.out.println("Going to match PLUS args");
					
				arg1=expr(_t);
				_t = _retTree;
				arg2=expr(_t);
				_t = _retTree;
				
						object = getTempAtomicVar(findType(0), ""); //@author dlariviere - utilizes helper function instead of repeating the same code over and over
						exprInstruct = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_SUBTRACTION, arg1, arg2, object);
						iSet.append(exprInstruct);
					
				_t = __t651;
				_t = _t.getNextSibling();
				break;
			}
			case MUL:
			{
				AST __t652 = _t;
				AST tmp12_AST_in = (AST)_t;
				match(_t,MUL);
				_t = _t.getFirstChild();
				
						Variable arg1, arg2;
						System.out.println("Going to match MUL args");
					
				arg1=expr(_t);
				_t = _retTree;
				arg2=expr(_t);
				_t = _retTree;
				
						object = getTempAtomicVar(findType(0), ""); //This is the temporary variable we will use to store the result.
						exprInstruct = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_MULTIPLICATION, arg1, arg2, object);
						iSet.append(exprInstruct);
					
				_t = __t652;
				_t = _t.getNextSibling();
				break;
			}
			case DIV:
			{
				AST __t653 = _t;
				AST tmp13_AST_in = (AST)_t;
				match(_t,DIV);
				_t = _t.getFirstChild();
				
						Variable arg1, arg2;
						System.out.println("Going to match DIV args");
					
				arg1=expr(_t);
				_t = _retTree;
				arg2=expr(_t);
				_t = _retTree;
				
						object = getTempAtomicVar(findType(0), ""); //This is the temporary variable we will use to store the result.
						exprInstruct = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_DIVISION, arg1, arg2, object);
						iSet.append(exprInstruct);
					
				_t = __t653;
				_t = _t.getNextSibling();
				break;
			}
			case ID:
			{
				AST __t654 = _t;
				AST tmp14_AST_in = (AST)_t;
				match(_t,ID);
				_t = _t.getFirstChild();
				
						int numChildren = tmp14_AST_in.getNumberOfChildren(); //number of children of this indicates whether it is a simple id, or an id[expr], where expr is a child node
						Variable indexVar = null; 		//only used if #ID is followed by exactly one expression as its child 
						Variable parentVar = null; 		//only used if indexed ID, contains the parent
						Variable tempConvert = null; 	//used only if conversion is necessary
						Variable tempCheck = null; 		//holds var object during analysis
						
						//if no children, just an identifier (no [0] or .real, etc) 
						if (numChildren==0) { 
							tempCheck = table.getVariable(tmp14_AST_in.getText());
							object = tempCheck;
							if(isArrayOp() && (!(tempCheck.isArray() && tempCheck.getDataType() == findType(0) && tempCheck.getArraySize() == getSize()) || !tempCheck.isArray()))
							{
								throw new SemanticAnalysisException(null, "Arrays in array operations must be of the same length; array/atomic arithmatic operations not supported");
							}
							else if(needsConversion(tempCheck.getDataType()))
							{
								System.out.println(tmp14_AST_in.getText() + " needs a conversion from " + tempCheck.getDataType() + " to " + findType(tempCheck.getDataType())); 
								if (findType(tempCheck.getDataType())==tempCheck.getDataType()) { 
									throw new Error("converting to same data type"); 	
								}
								tempConvert = getTempAtomicVar(findType(tempCheck.getDataType()), "");
								iSet.append(new ArithmaticInstruction(ArithmaticInstruction.OPERATION_CONVERSION, tempCheck, null, tempConvert));
								object = tempConvert;
							}			
						}
						else if (numChildren>3) { //greater than 3 since there is LBRACK (actual expression) RBRACK
							throw new Error("Error: more than one expression following an identifier, must be zero or one (\"[0]\" or \".real\" for example)"); 	
						}
						else { //one child, must be either an index into the element, or a .real/.imag first complex
							//tempValue = Variable.getNewAtomic(Variable.LITERAL_int, "_temp"+(nextTempNumber++), 0, false);
							parentVar = table.getVariable(tmp14_AST_in.getText());
							
							//table.addVariable(tempValue);
							//object = tempValue; //This is the temporary variable we will use to store the result.
						}
					
				{
				if (_t==null) _t=ASTNULL;
				switch ( _t.getType()) {
				case LBRACK:
				{
					AST tmp15_AST_in = (AST)_t;
					match(_t,LBRACK);
					_t = _t.getNextSibling();
					incrementIndexCount();
					indexVar=expr(_t);
					_t = _retTree;
					AST tmp16_AST_in = (AST)_t;
					match(_t,RBRACK);
					_t = _t.getNextSibling();
					decrementIndexCount();
					
								if (indexVar.isConstant() && indexVar.getIdentifier().substring(0,1).compareTo("-") == 0)
									throw new SymbolicException(parentVar, " : Array index accesses cannot be negative");
								if (indexVar.isArray())
									throw new SymbolicException(indexVar, " : An array cannot be the index of an array");
								if (indexVar.isElement()) { //handle if expression is another indexed id, for example "a[b[0]] = 5;" 
									//move the element ("b[0]", in the example above) into a temporary variable and then use that variable as the new index element
									Variable tempIndexValue = getTempAtomicVar(Variable.LITERAL_int, "");
									exprInstruct = new ArithmaticInstruction(ArithmaticInstruction.OPERATION_ASSIGNMENT, indexVar, null, tempIndexValue);
									iSet.append(exprInstruct);
									indexVar = tempIndexValue; //the index into the expression is now the temp variable
									//throw new Error("Error: indexes must be either constants or atomic elements, double indexing (\"a[b[i]] = 5;\") is not yet implemented\n"); 	
								}
								try { 
									Variable elementVar = Variable.getNewAtomicElement(parentVar, indexVar, 0); 
									object = elementVar;
									if(needsConversion(elementVar.getDataType()))	//Checks to see if conversion is necessary based on save type
									{
										System.out.println("Converting array element var from " + elementVar.getDataType() + " to " + findType(elementVar.getDataType())); 
										tempConvert = getTempAtomicVar(findType(elementVar.getDataType()), ""); //modified dlariviere - needed findType(), else it wasn't actually converting to the right type, but instead to itself
										iSet.append(new ArithmaticInstruction(ArithmaticInstruction.OPERATION_CONVERSION, elementVar, null, tempConvert));
										object = tempConvert;
									}
									
								} catch (Exception ex) { //catch a possible exception thrown
									throw new SemanticAnalysisException(null,"Array index out of bounds at ");  //throw the only type of expression that ANTLR's walker is already throwing 
								}
								
							
					break;
				}
				case 3:
				{
					break;
				}
				default:
				{
					throw new NoViableAltException(_t);
				}
				}
				}
				_t = __t654;
				_t = _t.getNextSibling();
				break;
			}
			case NUM:
			{
				{
				AST tmp17_AST_in = (AST)_t;
				match(_t,NUM);
				_t = _t.getNextSibling();
				
						try
						{
							if(findType(1) != Variable.DATA_TYPE_FLOAT)
							{
								object = Variable.getNewAtomic(Variable.getAntlrTypeFromVarType(findType(1)), tmp17_AST_in.getText(), 1, true); 
							}
							else
							{
								object = newFloatConstant(tmp17_AST_in.getText());
							}
						}
						catch(NumberFormatException e)
						{
							throw new SemanticAnalysisException(null, "Number to large for assignment");
						}
					
				}
				break;
			}
			case REAL:
			{
				{
				AST tmp18_AST_in = (AST)_t;
				match(_t,REAL);
				_t = _t.getNextSibling();
				Variable myReal = null;
				
						/**
						 * Added by dlariviere. x87 FPU has no load immediate for arbitrary constnats (only a few special cases)<br>
						 * Therefore float constants, unlike all other constants, must be added to the sybmol table and treated as actual variables, not constants. 
						 */
						System.out.println("Found real: " + tmp18_AST_in.getText());
						object = newFloatConstant(tmp18_AST_in.getText());
					
				}
				break;
			}
			case STRING:
			{
				{
				AST tmp19_AST_in = (AST)_t;
				match(_t,STRING);
				_t = _t.getNextSibling();
				
					  	try
					  	{
					  		object = table.addStringVariable(tmp19_AST_in.getText());  // @author Dave, actually add the variable to the symbol table
					  	}
					  	catch(SymbolicException e)
					  	{ 
					  		throw new SemanticAnalysisException((DSPLAST)_t,"Failed on String Constant: " + e.getMessage());
					  	}
					
				}
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return object;
	}
	
/**ccallname is unlike other instances of ID because we don't want a variable, we just want
 * the name of the function!
 */
	public final String  ccallname(AST _t) throws RecognitionException {
		String name;
		
		AST ccallname_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
			name = null;
		
		
		try {      // for error handling
			AST tmp20_AST_in = (AST)_t;
			match(_t,ID);
			_t = _t.getNextSibling();
			name = tmp20_AST_in.getText();
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return name;
	}
	
	public final Comparison  bool(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		Comparison s;
		
		AST bool_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
			Variable e1, e2;
			s = null;
		
		
		try {      // for error handling
			if (_t==null) _t=ASTNULL;
			switch ( _t.getType()) {
			case GT:
			{
				AST __t642 = _t;
				AST tmp21_AST_in = (AST)_t;
				match(_t,GT);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add greater than");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_GREATER);
					
				_t = __t642;
				_t = _t.getNextSibling();
				break;
			}
			case LT:
			{
				AST __t643 = _t;
				AST tmp22_AST_in = (AST)_t;
				match(_t,LT);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add less than");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_LESS);
					
				_t = __t643;
				_t = _t.getNextSibling();
				break;
			}
			case GE:
			{
				AST __t644 = _t;
				AST tmp23_AST_in = (AST)_t;
				match(_t,GE);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add greater than or equal to");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_GE);
					
				_t = __t644;
				_t = _t.getNextSibling();
				break;
			}
			case LE:
			{
				AST __t645 = _t;
				AST tmp24_AST_in = (AST)_t;
				match(_t,LE);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add less than or equal to");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_LE);
					
				_t = __t645;
				_t = _t.getNextSibling();
				break;
			}
			case EQ:
			{
				AST __t646 = _t;
				AST tmp25_AST_in = (AST)_t;
				match(_t,EQ);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add equal to");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_EQUAL);
					
				_t = __t646;
				_t = _t.getNextSibling();
				break;
			}
			case NE:
			{
				AST __t647 = _t;
				AST tmp26_AST_in = (AST)_t;
				match(_t,NE);
				_t = _t.getFirstChild();
				e1=expr(_t);
				_t = _retTree;
				e2=expr(_t);
				_t = _retTree;
				
						Variable exchange = null;
						System.out.println("Going to add not equal to");
						switch(checkLogical(e1,e2,_t))
						{
							case 1: exchange = getTempAtomicVar(e2.getDataType(), "");
									exchange.setValue(String.valueOf(e1.getValue()));
									e1 = exchange;
									break;
							case 2: exchange = getTempAtomicVar(e1.getDataType(), "");
									exchange.setValue(String.valueOf(e2.getValue()));
									e2 = exchange;
									break;
							default: //nothing
									break;
						}
						s = new Comparison(e1, e2, Comparison.CONDITION_NEQUAL);
					
				_t = __t647;
				_t = _t.getNextSibling();
				break;
			}
			default:
			{
				throw new NoViableAltException(_t);
			}
			}
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return s;
	}
	
	public final Instruction  subprog(AST _t) throws RecognitionException, SemanticAnalysisException,SymbolicException {
		Instruction s;
		
		AST subprog_AST_in = (_t == ASTNULL) ? null : (AST)_t;
		
			InstructionSet superIset = iSet;
			iSet = new InstructionSet();
			s = null;
		
		
		try {      // for error handling
			AST __t639 = _t;
			AST tmp27_AST_in = (AST)_t;
			match(_t,LBRACE);
			_t = _t.getFirstChild();
			{
			s=stmts(_t);
			_t = _retTree;
			}
			_t = __t639;
			_t = _t.getNextSibling();
			s = iSet.first(); iSet = superIset;
		}
		catch (RecognitionException ex) {
			reportError(ex);
			if (_t!=null) {_t = _t.getNextSibling();}
		}
		_retTree = _t;
		return s;
	}
	
	
	public static final String[] _tokenNames = {
		"<0>",
		"EOF",
		"<2>",
		"NULL_TREE_LOOKAHEAD",
		"NEGATE",
		"DECLS",
		"PROGRAM",
		"LBRACE",
		"RBRACE",
		"\"string\"",
		"\"int\"",
		"\"uint\"",
		"\"byte\"",
		"\"ubyte\"",
		"\"float\"",
		"\"complex\"",
		"ID",
		"SEMI",
		"\"complex_array\"",
		"\"int_array\"",
		"\"uint_array\"",
		"\"byte_array\"",
		"\"ubyte_array\"",
		"\"float_array\"",
		"LBRACK",
		"NUM",
		"RBRACK",
		"\"if\"",
		"LPAREN",
		"RPAREN",
		"\"else\"",
		"\"while\"",
		"\"for\"",
		"COMMA",
		"\"ccall\"",
		"ASSIGN",
		"EQ",
		"NE",
		"LT",
		"LE",
		"GT",
		"GE",
		"PLUS",
		"MINUS",
		"MUL",
		"DIV",
		"REAL",
		"STRING",
		"NEWLINE",
		"DIGITS",
		"TILDE",
		"DOT",
		"WS",
		"COMMENT"
	};
	
	private static final long[] mk_tokenSet_0() {
		long[] data = { 277076963819536L, 0L};
		return data;
	}
	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
	private static final long[] mk_tokenSet_1() {
		long[] data = { 58116276224L, 0L};
		return data;
	}
	public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
	}
	
