Add branching commands
This commit is contained in:
parent
3fdf4c1281
commit
cdd7e2a99c
28
templates.h
28
templates.h
|
@ -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
|
||||||
|
|
60
translator.c
60
translator.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue