Add branching commands

This commit is contained in:
Augusto Gunsch 2020-11-14 12:31:57 -03:00
parent 3fdf4c1281
commit cdd7e2a99c
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
3 changed files with 78 additions and 11 deletions

View File

@ -105,10 +105,9 @@ char* tnot[TNOTN] = {
"M=!M", "M=!M",
}; };
#define TCOMPN 15 #define TCOMPN 14
char* tcomp[TCOMPN] = { char* tcomp[TCOMPN] = {
"", "",
"M=D",
"@SP", "@SP",
"M=M-1", "M=M-1",
"A=M", "A=M",
@ -123,4 +122,29 @@ char* tcomp[TCOMPN] = {
"M=0", "M=0",
"" ""
}; };
#define TLABELN 2
char* tlabel[TLABELN] = {
"",
""
};
#define TGOTON 3
char* tgoto[TGOTON] = {
"",
"",
"0;JMP"
};
#define TIFGOTON 7
char* tifgoto[TIFGOTON] = {
"",
"@SP",
"M=M-1",
"A=M",
"D=M",
"",
"D;JNE"
};
#endif #endif

View File

@ -4,7 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include "translator.h" #include "translator.h"
#include "templates.h" #include "templates.h"
#define CMPLIMIT 1000 #define CMPLIMIT 9999
#define CMPLEN 4 #define CMPLEN 4
void pushtoclean(struct Translator* t, char* topush) { void pushtoclean(struct Translator* t, char* topush) {
@ -113,9 +113,9 @@ char* mkcmplab(struct Translator* t, struct line* ln) {
fprintf(stderr, "Reached comparison limit (%i); line %i\n", CMPLIMIT, ln->truen); fprintf(stderr, "Reached comparison limit (%i); line %i\n", CMPLIMIT, ln->truen);
exit(1); exit(1);
} }
int newsz = (CMPLEN+13)*sizeof(char); int newsz = (t->fnamelen + CMPLEN + 6) * sizeof(char);
char* label = (char*)malloc(newsz); char* label = (char*)malloc(newsz);
snprintf(label, newsz, "COMPARISON-%i", t->compcount); snprintf(label, newsz, "%s-CMP-%i", t->fname, t->compcount);
pushtoclean(t, label); pushtoclean(t, label);
return label; return label;
} }
@ -147,8 +147,7 @@ char* mklab(struct Translator* t, char* label, int labellen) {
char* mkstatind(struct Translator* t, struct line* ln, int indlen) { char* mkstatind(struct Translator* t, struct line* ln, int indlen) {
checkind(ln, indlen); checkind(ln, indlen);
int fnamelen = strlen(t->fname); int newsz = sizeof(char) * (t->fnamelen + indlen + 3);
int newsz = sizeof(char) * (fnamelen + indlen + 3);
char* newind = (char*)malloc(newsz); char* newind = (char*)malloc(newsz);
snprintf(newind, newsz, "@%s.%s", t->fname, ln->tokens[2]); snprintf(newind, newsz, "@%s.%s", t->fname, ln->tokens[2]);
pushtoclean(t, newind); pushtoclean(t, newind);
@ -327,14 +326,50 @@ void comp(struct Translator* t, struct line* ln, char* op) {
char* trueop = (char*)malloc(opsz); char* trueop = (char*)malloc(opsz);
snprintf(trueop, opsz, "D;J%s", op); snprintf(trueop, opsz, "D;J%s", op);
tcomp[TCOMPN-5] = trueop; tcomp[TCOMPN-5] = trueop;
pushtoclean(t, trueop);
// (label) // (label)
tcomp[TCOMPN-1] = mklab(t, label, labellen); tcomp[TCOMPN-1] = mklab(t, label, labellen);
free(label);
addasmlns(t, ln, tcomp, TCOMPN); addasmlns(t, ln, tcomp, TCOMPN);
}; };
void label(struct Translator* t, struct line* ln) {
if(ln->tokenscount < 2) {
fprintf(stderr, "Expected label; line %i", ln->truen);
exit(1);
}
// (label)
tlabel[TLABELN-1] = mklab(t, ln->tokens[1], strlen(ln->tokens[1]));
addasmlns(t, ln, tlabel, TLABELN);
}
void mygoto(struct Translator* t, struct line* ln) {
if(ln->tokenscount < 2) {
fprintf(stderr, "Expected label; line %i", ln->truen);
exit(1);
}
// @label
tgoto[TGOTON-2] = atlab(t, ln->tokens[1], strlen(ln->tokens[1]));
addasmlns(t, ln, tgoto, TGOTON);
}
void ifgoto(struct Translator* t, struct line* ln) {
if(ln->tokenscount < 2) {
fprintf(stderr, "Expected label; line %i", ln->truen);
exit(1);
}
// @label
tifgoto[TIFGOTON-2] = atlab(t, ln->tokens[1], strlen(ln->tokens[1]));
addasmlns(t, ln, tifgoto, TIFGOTON);
}
void switchpush(struct Translator* t, struct line* ln) { void switchpush(struct Translator* t, struct line* ln) {
checkopamnt(3, ln); checkopamnt(3, ln);
char* seg = ln->tokens[1]; char* seg = ln->tokens[1];
@ -375,7 +410,7 @@ void switchop(struct Translator* t, struct line* ln) {
else if(!strcmp(op, "pop")) else if(!strcmp(op, "pop"))
switchpop(t, ln); switchpop(t, ln);
else if(!strcmp(op, "add")) else if(!strcmp(op, "add"))
arith(t, ln, "M=M+D"); arith(t, ln, "M=D+M");
else if(!strcmp(op, "sub")) else if(!strcmp(op, "sub"))
arith(t, ln, "M=M-D"); arith(t, ln, "M=M-D");
else if(!strcmp(op, "neg")) else if(!strcmp(op, "neg"))
@ -387,11 +422,17 @@ void switchop(struct Translator* t, struct line* ln) {
else if(!strcmp(op, "lt")) else if(!strcmp(op, "lt"))
comp(t, ln, "GT"); comp(t, ln, "GT");
else if(!strcmp(op, "and")) else if(!strcmp(op, "and"))
arith(t, ln, "M=M&D"); arith(t, ln, "M=D&M");
else if(!strcmp(op, "or")) else if(!strcmp(op, "or"))
arith(t, ln, "M=M|D"); arith(t, ln, "M=D|M");
else if(!strcmp(op, "not")) else if(!strcmp(op, "not"))
addasmlns(t, ln, tnot, TNOTN); addasmlns(t, ln, tnot, TNOTN);
else if(!strcmp(op, "label"))
label(t, ln);
else if(!strcmp(op, "goto"))
mygoto(t, ln);
else if(!strcmp(op, "if-goto"))
ifgoto(t, ln);
else { else {
fprintf(stderr, "Unrecognized operation '%s'; line %i\n", op, ln->truen); fprintf(stderr, "Unrecognized operation '%s'; line %i\n", op, ln->truen);
exit(1); exit(1);
@ -416,6 +457,7 @@ struct Translator* mktranslator(struct lnarray* lns, char* fname) {
t->lns = lns; t->lns = lns;
t->fname = fname; t->fname = fname;
t->fnamelen = strlen(fname);
return t; return t;
} }

View File

@ -16,6 +16,7 @@ struct Translator {
int tocleanind; int tocleanind;
struct lnarray* lns; struct lnarray* lns;
char* fname; char* fname;
int fnamelen;
int compcount; int compcount;
}; };