#ifndef INTERPRETER_H    
#define INTERPRETER_H 
//**************************************************************************************
//**************************************************************************************


#include <vector>
#include <list>
#include <cstdlib>
#include <iostream>
#include "lexScanner.h"
#include "expEvaluator.h"
#include "syntax.h"
using namespace std;

#include <conio.h>		//including support to use getch()
						//	to read one raw character from user input

class Interpreter
{
	private:
	//****************************************************************
	//*****			Section of Private data members				******
	//****************************************************************
			//********************************************************************
			//***	Sytax information stored in an SyntaxAnalyzer object  ******
			//********************************************************************
			SyntaxAnalyzer mySyntax;

			//********************************************************************
			//******		Runtime & execution information					******
			//********************************************************************
			list<functionCodeRecord> stackOfActivatedFunctionCodeRecords;
			//For each valid function call made,
			//	we make a duplicate of the corresponding functionCodeRecord and 
			//	activate it as a new functionCodeRecord on top of 
			//	the stack of activated function code records.
			//And when we execute this particular function call, we will use the
			//	localVariablesTable associated with this copy of functionCodeRecord.
			//This allows us to deal with recursive function calls, and
			//	makes it easy to trace this stack at any point at time
			//	to see the thread of function calls and the current values of 
			//	local variables within the context of these function calls.

			bool debugModeStatus;
			//About how execution traces & debugging information is shown

			bool programReadyForExecution;
			//Whether the source code has been parsed and ready for execution

	public:
	//****************************************************************
	//*****			Section of Public member functions	     	******
	//****************************************************************

		Interpreter();
		//constructor function that makes the interpreter refer to 
		//	the source code program pointed to by aPtrToSourceProgram.

		bool executeProgram(vector<string> & sourceProgram);
		//Ask the user to make an entry function call to run the program
		//Execute a function call to a function defined in the program.
		//The command is expected to be of the form 
		//		functionName(argument,argument,...)
		//		For example:		main()		gcd(4,8)
		//Return true if the execution is completed successfully;
		//	otherwise return false.


		void outputParseTree(vector<string> & sourceProgram, const char * outputFileName);
		//Use the SyntaxAnalyzer to output a parse tree for the code in sourceProgram
		//Save it into the file whose name is stored in outputFileName
		

		//********************************************************************
		//*****		Other public member functions for house keeping		******
		//********************************************************************

		void displayStackOfActivatedFunctionCodeRecords();
		//Display the information in the stackOfActivatedFunctionCodeRecords
		//	i.e. all the pending function calls

		bool isProgramReadyForExecution()
		{ return programReadyForExecution;
		}
		//Inline function: Indicate whether the program is ready 
		//	for execution

		void setProgramStatusAsModified()
		{ programReadyForExecution=false;
		}
		//Inline function: Indicate the source code has been modified and not ready 
		//	for execution

		void setProgramStatusAsReadyForExecution()
		{ programReadyForExecution=true;
		}
		//Inline function: Indicate the source code has been parsed and is ready 
		//	for execution without rebuilding syntactic and semantic information

		bool isDebugModeOn()
		{ return debugModeStatus;
		}
		//Inline function: Indicate whether the debug mode is on (true)

		bool setDebugMode(bool status=true)
		{ debugModeStatus = status; return debugModeStatus;
		}
		//Inline function: Set the debug mode to the specified status

		bool toggleDebugMode()
		{ debugModeStatus = !debugModeStatus; return debugModeStatus;
		}
		//Inline function: Toggle the current debug mode


	private:
	//********************************************************************
	//*****			Section of Private member functions				******
	//********************************************************************
			//********************************************************************
			//*****		Private member functions for program execution		******
			//********************************************************************
			bool executeFunctionCall
				(	string functionName, 
					vector<float> argumentsList,
					float & result
				);
			//Execute a function call to a function with functionNamethe as name 
			//	and argumentsList as the values of the parameters.
			//If the function call is correctly finished, return true and 
			//	store the return value of the call in result;
			//otherwise, return false.
			//
			//The functions below are used in the implementation for this function.

				bool executeOneMoreInterpreterInstruction
				(	int indexThisInterpreterInstruction, 
					symbolTable & localVariablesTable,
					float & result
				);
				//Execute one interpreter instruction with respect to 
				//	a table of local variables table.
				//Return false and store the return value in result
				//	if executing a return statement;
				//Otherwise, simply return true in the end.

				int getIndexNextInterpreterInstructionToExecute
					(	int indexThisInterpreterInstruction,
						symbolTable & localVariablesTable
					);
				//Get the index of the next interpreter instruction to execute
				//	given the localVariablesTable


				bool executeDisplayInterpreterInstruction
				(	perLineTokenVector & displayInterpreterInstruction,
					symbolTable & localVariablesTable
				);
				//Do the evaluation and output all the things a a display statement.
				//	If somthing wrong in the execution, return true; 
				//	othersie return false.


				bool getCommandString
				(string command, string & functionName, vector<float>& argumentsList);
				//Parse the command string to get function name and the argument list.
				//This fucntion is called by the executeProgram function to
				//	analyze the user command.



				bool getFunctionNameAndArgumentsListFromFunctionCallAssignmemt
					(	vector<string> & functionCallInterpreterInstruction,
						symbolTable & localVariablesTable,
						string & functionName,
						vector<float> & argumentsList
					);
				//Get the function name and the argument list from
				//	a functionCallAssignment Interpreter Instruction.
				//For example, from the following interpreter instruction
				//		x = gcd(4+6, y-1)
				//with variable value 1 for y,
				//	this function will derives "gcd" as the function name and 
				//	a vector of two values: 10 and 0 as the argument list.


			//********************************************************************
			//*****		Private member functions for debugging purposes		******
			//********************************************************************

			void debugBreakPoint(string messageForUser)
			{ if (debugModeStatus==false)
				return;
				cout << messageForUser << endl << "Press any key to continue: " ;
				getch();
				// Ano alternative to getchar : //char wait;	//cin >> wait;
				cout << endl;
			}
			//Inline function: Set a breakpoint in execution when the debug mode is on

			void breakPoint(string messageForUser)
			{ 	cout << messageForUser << endl 
					 << '\t' << "Press any key to continue: " ;
				getch();
				// Ano alternative to getchar : //char wait;	//cin >> wait;
				cout << endl;
			}
			//Inline function: Set a breakpoint in execution 
};

//**************************************************************************************
//**************************************************************************************
#endif // Matching the starting #ifndef INTERPRETER_H 