All pastes #1468149 Raw Edit

CodeWriter.cpp

public text v1 · immutable
#1468149 ·published 2009-06-20 23:02 UTC
rendered paste body
#include "CodeWriter.h"
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>

using namespace std;

CodeWriter::CodeWriter(string name)
{
	string temp;
	temp=(name.substr(0,name.length()-2))+"asm";
	name1=name.substr(0,name.length()-3);
	tname.open(temp.c_str());
}

void CodeWriter::writeArithmetic(string command,int a)
{
	int i=0;
	string asmCom="",num;
	if(a==0)
		num="0";
	while(a!=0)
	{
		num+=a%10+'0';
		a/=10;
		i++;
	}
	reverse(num.begin(),num.end());

	if(command.substr(0,3)=="add")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D+M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=D\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}
	if(command.substr(0,3)=="sub")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D-M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=D\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}
	if(command.substr(0,3)=="neg")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="M=-M\n";
	}
	
	if(command.substr(0,2)=="eq")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D-M\n";
		asmCom+="@EQ";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="D;JEQ\n";
		asmCom+="(NEQ";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=0\n";
		asmCom+="@END";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="0;JMP\n";
		asmCom+="(EQ";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=-1\n";
		asmCom+="(END";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}

	if(command.substr(0,2)=="gt")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D-M\n";
		asmCom+="@GR";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="D;JGT\n";
		asmCom+="(NG";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=0\n";
		asmCom+="@END";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="0;JMP\n";
		asmCom+="(GR";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=-1\n";
		asmCom+="(END";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}

	if(command.substr(0,2)=="lt")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D-M\n";
		asmCom+="@LS";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="D;JLT\n";
		asmCom+="(NL";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=0\n";
		asmCom+="@END";
		asmCom+=num;
		asmCom+="\n";
		asmCom+="0;JMP\n";
		asmCom+="(LS";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=-1\n";
		asmCom+="(END";
		asmCom+=num;
		asmCom+=")\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}

	if(command.substr(0,3)=="and")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D&M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=D\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}

	if(command.substr(0,2)=="or")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D|M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=D\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
	}

	if(command.substr(0,3)=="not")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="M=!M\n";
	}
	
	if(command.substr(0,4)=="nand")
	{
		asmCom="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="D=M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="D=D&M\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="A=A-1\n";
		asmCom+="M=D\n";
		asmCom+="@SP\n";
		asmCom+="M=M-1\n";
		asmCom+="@SP\n";
		asmCom+="A=M-1\n";
		asmCom+="M=!M\n";
	}

	tname<<asmCom;
}


void CodeWriter::writePushPop(string command, string segment, int index)
{
	int i=0,k=1,temp;
	string asmCom="",num;
	temp=index;
	if(index==0)
		num="0";
	while(temp!=0)
	{
		num+=temp%10+'0';
		temp/=10;
		i++;
	}
	reverse(num.begin(),num.end());

	if(command=="C_PUSH")
	{
		if(segment=="constant")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";

		}

		if(segment=="local")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@LCL\n";
			asmCom+="A=M+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}

		if(segment=="argument")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@ARG\n";
			asmCom+="A=M+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}

		if(segment=="this")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@THIS\n";
			asmCom+="A=M+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}

		if(segment=="that")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@THAT\n";
			asmCom+="A=M+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}

		if(segment=="pointer")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@3\n";
			asmCom+="A=A+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}

		if(segment=="temp")
		{
			asmCom="@";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=A\n";
			asmCom+="@5\n";
			asmCom+="A=A+D\n";
			//asmCom+="A=M\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";;
		}

		if(segment=="static")
		{
			num=index+'0';
			asmCom="@";
			asmCom+=name1;
			asmCom+=".";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="D=M\n";
			asmCom+="@SP\n";
			asmCom+="A=M\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M+1\n";
		}
	}

	if(command=="C_POP")
	{
		if(segment=="local")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@LCL\n";
			asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}

		if(segment=="argument")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@ARG\n";
			asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}

		if(segment=="this")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@THIS\n";
			asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}

		if(segment=="that")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@THAT\n";
			asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}

		if(segment=="pointer")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@3\n";
			//asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}
		if(segment=="temp")
		{
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			asmCom+="@5\n";
			//asmCom+="A=M\n";
			for(int i=0;i<index;i++)
				asmCom+="A=A+1\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}

		if(segment=="static")
		{
			
			asmCom="@SP\n";
			asmCom+="A=M-1\n";
			asmCom+="D=M\n";
			num=index+'0';
			asmCom+="@";
			asmCom+=name1;
			asmCom+=".";
			asmCom+=num;
			asmCom+="\n";
			asmCom+="M=D\n";
			asmCom+="@SP\n";
			asmCom+="M=M-1\n";
		}


	}

	tname<<asmCom;
}


void CodeWriter::close()
{
	tname<<"\n";
	tname.close();
}


void CodeWriter::writeInit()
{
	string asmCom="";
	asmCom="@256\n";
	asmCom+="D=A\n";
	asmCom+="@SP\n";
	asmCom+="M=D\n";
	/*asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	asmCom+="M=M+1\n";
	asmCom+="M=M+1\n";
	asmCom+="M=M+1\n";
	asmCom+="M=M+1\n";
	asmCom+="@";
	asmCom+="Sys.init";
	asmCom+="\n";
	asmCom+="0;JMP\n";*/
	tname<<asmCom;
	
	writeCall("Sys.init",0,0);
	
	
}
	

void CodeWriter::writeLabel(string label)//dont forget to add a variable in main that 
										//gets the name of the current function. 
										//and to add the current function name to label with a $ sign
{
	string asmCom;

	asmCom="(";
	asmCom+=label;
	asmCom+=")\n";

	tname<<asmCom;
}

void CodeWriter::writeGoto(string label)
{
	string asmCom;

	asmCom="@";
	asmCom+=label;
	asmCom+="\n0;JMP\n";

	tname<<asmCom;
}

void CodeWriter::writeIf(string label,int a)//to turn the var. "a" in main to global var. so this function will be able to cahnge it 
{
	string asmCom;

	writePushPop("C_PUSH","constant",0);
	writeArithmetic("eq",a);
	asmCom="@SP\n";
	asmCom+="A=M\n";
	asmCom+="A=A-1\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="M=M-1\n";
	asmCom+="@";
	asmCom+=label;
	asmCom+="\nD;JEQ\n";

	tname<<asmCom;
}

void CodeWriter::writeCall(string functionName, int numArg,int a)
{
	int temp=0,i=0,temp1=0,j=0;
	string asmCom,num,num1;
	temp=numArg;
	if(numArg==0)
		num="0";
	while(temp!=0)
	{
		num+=temp%10+'0';
		temp/=10;
		i++;
	}
	reverse(num.begin(),num.end());
	temp1=a;
	if(a==0)
		num1="0";
	while(temp1!=0)
	{
		num1+=temp1%10+'0';
		temp1/=10;
		j++;
	}
	reverse(num1.begin(),num1.end());


	asmCom="@";
	asmCom+=functionName;
	asmCom+="_return_address";
	asmCom+=num1;
	asmCom+="\n";
	asmCom+="D=A\n";//D=M
	asmCom+="@SP\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	//tname<<asmCom;
	asmCom+="@LCL\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	//writePushPop("C_PUSH","local",0);
	asmCom+="@ARG\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	//writePushPop("C_PUSH","argument",0);
	asmCom+="@THIS\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	//writePushPop("C_PUSH","this",0);
	asmCom+="@THAT\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="M=M+1\n";
	//writePushPop("C_PUSH","that",0);
	asmCom+="@SP\n";
	asmCom+="D=M\n";///D=A
	asmCom+="@";
	asmCom+=num;
	asmCom+="\n";
	asmCom+="D=D-A\n";
	asmCom+="@5\n";
	asmCom+="D=D-A\n";
	asmCom+="@ARG\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="D=M\n";//D=A
	asmCom+="@LCL\n";
	asmCom+="M=D\n";
	asmCom+="@";
	asmCom+=functionName;
	asmCom+="\n";
	asmCom+="0;JMP\n";
	asmCom+="(";
	asmCom+=functionName;
	asmCom+="_return_address";
	asmCom+=num1;
	asmCom+=")\n";
	
	tname<<asmCom;
}

void CodeWriter::writeReturn()
{
	string asmCom;
	asmCom+="@LCL\n";
	asmCom+="D=M\n";
	asmCom+="@FRAME\n";
	asmCom+="M=D\n";
	asmCom+="@5\n";
	asmCom+="D=A\n";
	asmCom+="@FRAME\n";
	asmCom+="A=A-D\n";
	asmCom+="D=M\n";
	asmCom+="@RET\n";
	asmCom+="M=D\n";
	asmCom+="@SP\n";
	asmCom+="@A=M-1\n";
	asmCom+="@D=M\n";
	asmCom+="@ARG\n";
	asmCom+="A=M\n";
	asmCom+="M=D\n";


	asmCom+="D=A+1\n";
	asmCom+="@SP\n";
	asmCom+="M=D\n";
	
	asmCom+="@FRAME\n";
	asmCom+="A=M\n";
	asmCom+="A=A-1\n";
	asmCom+="D=M\n";
	asmCom+="@THAT\n";
	asmCom+="M=D\n";

	asmCom+="@2\n";
	asmCom+="D=A\n";
	asmCom+="@FRAME\n";
	asmCom+="A=M\n";
	asmCom+="A=A-D\n";
	asmCom+="D=M\n";
	asmCom+="@THIS\n";
	asmCom+="M=D\n";

	
	asmCom+="@3\n";
	asmCom+="D=A\n";
	asmCom+="@FRAME\n";
	asmCom+="A=M\n";
	asmCom+="A=A-D\n";
	asmCom+="D=M\n";
	asmCom+="@ARG\n";
	asmCom+="M=D\n";

	
	asmCom+="@4\n";
	asmCom+="D=A\n";
	asmCom+="@FRAME\n";
	asmCom+="A=M\n";
	asmCom+="A=A-D\n";
	asmCom+="D=M\n";
	asmCom+="@LCL\n";
	asmCom+="M=D\n";
	
	//writeGoto("RET");
	asmCom+="@RET\n";
	asmCom+="A=M\n";
	asmCom+="0;JMP\n";

	tname<<asmCom;
}


void CodeWriter::writeFunction(string functionName, int numLocals)
{
	string asmCom;
	int i=0;
	
	asmCom="(";
	asmCom+=functionName;
	asmCom+=")\n";
	tname<<asmCom;
	for(i=0;i<numLocals;i++)
		writePushPop("C_PUSH","constant",0);
}

void CodeWriter::SetName(char *s)
{
	name1=s;
}


void CodeWriter::writeIfNot(string label, int a)
{
	string asmCom;

	writePushPop("C_PUSH","constant",0);
	writeArithmetic("eq",a);
	asmCom="@SP\n";
	asmCom+="A=M\n";
	asmCom+="A=A-1\n";
	asmCom+="D=M\n";
	asmCom+="@SP\n";
	asmCom+="M=M-1\n";
	asmCom+="@";
	asmCom+=label;
	asmCom+="\nD;JNE\n";

	tname<<asmCom;
}