#ifndef INSTRUCTIONS
#define INSTRUCTIONS

const int NUM_INSTRUCTIONS = 5000;

class Instructions
{
public:
	Instructions(); // The constructor initializes the array of machine code to look like a function
	void Finish(); // Finalizes the array of machine code to look like a function
	void Execute(); // Causes the instruction pointer to jump into the array of machine code that behaves like a function

	// Getting numbers on and off the stack
	void PushValue(unsigned int value);  // used by IntegerNode
	void PushVariable(unsigned int index); // used by IdentifierNode
	void PopAndWrite(); // used by CoutStatementNode
	void WriteEndl();
	void PopAndStore(int index); // used by AssignmentStatementNode
	static int * GetPrintInteger();

	// Mathematical Operators
	void PopPopAddPush(); // Puts resulting integer on stack
	void PopPopSubPush(); 
	void PopPopMulPush(); 
	void PopPopDivPush(); 

	// Relational Operators
	void PopPopComparePush(unsigned char relational_operator); 
		// common code for the relational operators
		// Puts 1 or 0 on stack.
	void PopPopLessPush(); 
	void PopPopLessEqualPush(); 
	void PopPopGreaterPush(); 
	void PopPopGreaterEqualPush(); 
	void PopPopEqualPush(); 
	void PopPopNotEqualPush(); 

	// Logical Operators
	void PopPopAndPush();
	void PopPopOrPush();

	// Jumping around based on the top of stack being 1 or 0.
	unsigned char * SkipIfZeroStack(); // skips some number of bytes forward, if the integer on the stack is zero.
							// The number of bytes to skip forward MUST be set by calling SetOffset with the return value.
							// The number that was on the stack (1 or 0) gets popped as a side effect.
	unsigned char * GetAddress(); // returns the memory address where the next instruction will go.
	unsigned char * Jump(); // writes code to jump forward or backward some number of bytes.
							// The number of bytes to skip MUST be set by calling SetOffset with the return value.
							
	void SetOffset(unsigned char * codeAddress, int offset);

private:
	void Call(void * function_address);
	static int * GetMem(int index); // index is 0 based.

	void PrintIntegerValue();
	static int * mPrintInt;
	static unsigned char mInstructions[NUM_INSTRUCTIONS];

	int current;
};

#endif

