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;
}