/*
Function: gen3AC()

Description: 
*/
threeAC multExpr_Node::gen3AC(){
	//std::cout << "Generate 3AC for postfix expression node" << std::endl;
	if (exprA != NULL && exprB == NULL) {
		return exprA->gen3AC(); 
	}

	threeAC tempA = exprA->gen3AC();
	threeAC tempB = exprB->gen3AC(); 
	std::string reg = "";  
	switch(type) {
		case MULT:
			reg = intTC();
			//out3AC << ("MULT " + reg + " " + tempA.str + " " + tempB.str) << std::endl; 
			output3AC("MULT", reg, tempA.str, tempB.str); 
		break; 

		case DIV:
			reg = intTC();
			//out3AC << ("DIV " + reg + " " + tempA.str + " " + tempB.str) << std::endl; 
			output3AC("DIV", reg, tempA.str, tempB.str); 
		break;

		default:
			reg = ""; 
		break;
	}

	tempA.str = reg;
	return tempA; 
}
/*
Function: gen3AC()

Description: 
*/
threeAC assignmentExpr_Node::gen3AC(){
	//std::cout << "Generate 3AC for assignment expression node" << std::endl;
	if (exprA != NULL && exprB == NULL) {
		return exprA->gen3AC(); 
	}

	threeAC tempA = exprA->gen3AC();
	threeAC tempB = exprB->gen3AC(); 
	std::string reg = ""; 
	switch(type) {
		case ASSIGN:
			//out3AC << ("ASSIGN " + tempA.str + " " + tempB.str) << std::endl;
			output3AC("ASSIGN", tempA.str, tempB.str, "-");  
		break;

		case MUL_ASSIGN:
			reg = intTC();
			//out3AC << ("MUL " + reg + " " + tempA.str + " " + tempB.str) << std::endl;
			//out3AC << ("ASSIGN " + tempA.str + " " + reg) << std::endl;   
			output3AC("MUL", reg, tempA.str, tempB.str);  
			output3AC("ASSIGN", tempA.str, reg, "-");  
		break;

		case DIV_ASSIGN:
			reg = intTC();
			//out3AC << ("DIV " + reg + " " + tempA.str + " " + tempB.str) << std::endl;
			//out3AC << ("ASSIGN " + tempA.str + " " + reg) << std::endl;   
			output3AC("DIV", reg, tempA.str, tempB.str);  
			output3AC("ASSIGN", tempA.str, reg, "-");
		break;

		case ADD_ASSIGN:
			reg = intTC();
			//out3AC << ("ADD " + reg + " " + tempA.str + " " + tempB.str) << std::endl;
			//out3AC << ("ASSIGN " + tempA.str + " " + reg) << std::endl;  
			output3AC("ADD", reg, tempA.str, tempB.str);  
			output3AC("ASSIGN", tempA.str, reg, "-"); 
		break;

		case SUB_ASSIGN:
			reg = intTC();
			//out3AC << ("SUB " + reg + " " + tempA.str + " " + tempB.str) << std::endl;
			//out3AC << ("ASSIGN " + tempA.str + " " + reg) << std::endl;   
			output3AC("SUB", reg, tempA.str, tempB.str);  
			output3AC("ASSIGN", tempA.str, reg, "-");
		break;

		default:
			reg = "";
		break; 
	}
	 
	return tempA; 
}
/*
Function: gen3AC()

Description: 
*/
threeAC unaryExpr_Node::gen3AC(){
	//std::cout << "Generate 3AC for unary expression node" << std::endl;
	std::string reg = ""; 
	threeAC temp;

	if (exprA != NULL && exprB == NULL && !incOp && !decOp) {
		return exprA->gen3AC(); 
	}
	// if ++
	else if (incOp) {
		temp = exprB->gen3AC();
		reg = intTC(); 
		//out3AC << ("ADD " + reg + " " + temp.str + " 1") << std::endl;
		//out3AC << ("ASSIGN " + temp.str + " " + reg) << std::endl; 
		output3AC("ADD", reg, temp.str, "1");
		output3AC("ASSIGN", temp.str, reg, "-");
	}
	// if --
	else if (decOp) {
		temp = exprB->gen3AC();
		reg = intTC(); 
		//out3AC << ("SUB " + reg + " " + temp.str + " 1") << std::endl;
		//out3AC << ("ASSIGN " + temp.str + " " + reg) << std::endl; 
		output3AC("SUB", reg, temp.str, "1");
		output3AC("ASSIGN", temp.str, reg, "-");
	}
	// if -
	else if ( (exprB != NULL) && (dynamic_cast <unaryOp_Node*> (exprA))) {
		reg = intTC(); 
		//out3AC << ("MULT " + reg + " " + exprB->gen3AC().str + " -1") << std::endl;
		output3AC("MULT", reg, exprB->gen3AC().str, "-1");
		
	}

	temp.str = reg;
	return temp;
}
/*
Function: gen3AC()

Description: 
*/
threeAC postfixExpr_Node::gen3AC(){
	threeAC temp;
	std::string reg = "";

	// check for simple case
	if (exprA != NULL && exprB == NULL && !incOp && !decOp) {
		return exprA->gen3AC(); 
	}

	temp = exprA->gen3AC();
	if (temp.ste.isArray()) {
		threeAC tempB = exprB->gen3AC(); 

		// 2D array
		std::vector<int> arrDims = temp.ste.getArrayDimensions();
		if (arrDims.size() == 3) {
			std::string t1 = intTC();
			std::string t2 = intTC(); 
			std::string offset = intTC(); 
			//out3AC << ("MUL " + t1 + " " + tempB.str + " 4") << std::endl;
			//out3AC << ("MUL " + t2 + " " + t1 + " " + std::to_string(arrDims[1])) << std::endl;
			//out3AC << ("ADD " + offset + " " + temp.str + " " + t2) << std::endl;
			output3AC("MULT", t1, tempB.str, "4"); 
			output3AC("MULT", t2, t1, std::to_string(arrDims[2])); 
			output3AC("ADD", offset, temp.str, t2); 
			reg = offset; 

			// decrement dimension count
			arrDims.pop_back(); 
			temp.ste.setArrayDimensions(arrDims);
		}
		else if (arrDims.size() == 2) {
			std::string t1 = intTC();
			std::string t2 = intTC(); 
			std::string offset = intTC(); 
			//out3AC << ("MUL " + t1 + " " + tempB.str + " 4") << std::endl;
			//out3AC << ("MUL " + t2 + " " + t1 + " " + std::to_string(arrDims[1])) << std::endl;
			//out3AC << ("ADD " + offset + " " + temp.str + " " + t2) << std::endl;
			output3AC("MULT", t1, tempB.str, "4"); 
			output3AC("MULT", t2, t1, std::to_string(arrDims[1])); 
			output3AC("ADD", offset, temp.str, t2); 
			reg = offset; 

			// decrement dimension count
			arrDims[0] = arrDims[1];
			arrDims.pop_back(); 
			temp.ste.setArrayDimensions(arrDims);
		}

		// 1D array
		else if (arrDims.size() == 1) {
			std::string t1 = intTC();
			std::string t2 = intTC();
			//out3AC << ("MUL " + t1 + " " + tempB.str  + " 4") << std::endl;
			//out3AC << ("ADD " + t2 + " " + temp.str + " " + t1) << std::endl;
			output3AC("MULT", t1, tempB.str, "4"); 
			output3AC("ADD", t2, temp.str, t1);
			reg = t2;
		}
	}

	// check for increment
	if (incOp) {
		reg = intTC();
		temp = exprA->gen3AC();
		//out3AC << ("ADD " + reg + " " + temp.str + " 1") << std::endl;
		//out3AC << ("ASSIGN " + temp.str + " " + reg) << std::endl;   
		output3AC("ADD", reg, temp.str, "1"); 
		output3AC("ASSIGN", temp.str, reg, "-");
	} 

	// check for decrement
	else if (decOp) {
		reg = intTC(); 
		temp = exprA->gen3AC();
		//out3AC << ("SUB " + reg + " " + temp.str + " 1") << std::endl;
		//out3AC << ("ASSIGN " + temp.str + " " + reg) << std::endl; 
		output3AC("SUB", reg, temp.str, "1"); 
		output3AC("ASSIGN", temp.str, reg, "-");  
	} 

	temp.str = reg;
	return temp; 
}