// VM2ASMCompiler.cpp : Defines the entry point for the console application.
//
//Comment the following #include statement if you are not using Visual C++
#include "stdafx.h"

#include <string>
#include <stdlib.h>
#include <cstdlib>
#include "CodeWriter.h"
#include "VMParser.h"

#define __VERIFY_PARSER 1

/** Process
Parameter: 
sourcefile A const char pointer that contains the name of the VM file that should be parsed and translated.
cwPtr A pointer to a CodeWriter object that is used to compile each line of the source file.
Result:
Informs the CodeWriter about the name of the file that will be processed.
Creates a VMParser object, and iterates while the parser returns a new line.
Processes each line.
Returns:
Nothing
*/
void Process(const char* sourceFile, CodeWriter* cwPtr)
{
	if (!cwPtr) 
		return;
	cwPtr->setFileName(sourceFile);

	VMParser parser(sourceFile);
	while (parser.advance()) {
		CmdType cmd = parser.commandType();
#ifdef __VERIFY_PARSER
		if (__VERIFY_PARSER == 1)
		{
			parser.dump();
		}
#endif
		switch (cmd) {
		case C_ARITHMETIC:
			cwPtr->writeArithmetic(parser.arg1());
			break;
		case C_PUSH:
        case C_POP:
			cwPtr->writePushPop(cmd, parser.arg1(), parser.arg2());
            break;
        case C_LABEL:      
			cwPtr->writeLabel(parser.arg1());
			break;
        case C_GOTO:
			cwPtr->writeGoto(parser.arg1());
            break;
        case C_IF:
			cwPtr->writeIf(parser.arg1());
            break;
        case C_CALL:
			cwPtr->writeCall(parser.arg1(), parser.arg2());
            break;
        case C_RETURN:
			cwPtr->writeReturn();
            break;
        case C_FUNCTION:
			cwPtr->writeFunction(parser.arg1(), parser.arg2());
            break;
        default:
			cout << "Invalid command Type\n";
            exit(1);
		}
	}
}

/** _tmain
Parameter:
argc An integer parameter that specifies the number of command line arguments the program received
argv A char* array that contains the command line arguments. The first entry is the pathname of the executable.
Result:
Executes the compiler. Goes through all input VM files and compiles them into a single ASM file.
Returns:
0 on success
<>0 on error.
*/
int main(int argc, char* argv[])
{
	int firstFileArg = 1;
	if (argc>=2 && !strcmp(argv[1], "-nosysinit")) {
			firstFileArg++;
		}
	if (argc>=firstFileArg+2) {
			CodeWriter cw(argv[firstFileArg]);//the destination file
			cw.writeInit(firstFileArg == 1);
			for (int i = firstFileArg+1; i<argc; i++) {					   
				Process(argv[i], &cw);
		}
	}
	else
	{
		cout << "Use: ./VM2ASMCompiler [-nosysinit] <outfile.ASM> <infile1.VM> <infile2.VM> ...\n";
		return 1;
	}
	return 0;
}

