jack-compiler/compiler/compiler-statements.c

176 lines
4.5 KiB
C
Raw Normal View History

2020-12-31 18:02:04 -05:00
#include <stdlib.h>
#include <string.h>
#include "compiler-expressions.h"
#include "compiler-statements.h"
#include "compiler-util.h"
/* BEGIN FORWARD DECLARATIONS */
// Miscelaneous
LINE* popthat();
LINE* pushtemp();
char* mkcondlabel(char* name, int count);
// Handling individual statements
2021-01-06 19:18:52 -05:00
LINEBLOCK* compileret(SCOPE* s, STATEMENT* st);
LINEBLOCK* compileif(SCOPE* s, STATEMENT* st);
LINEBLOCK* compilewhile(SCOPE* s, STATEMENT* st);
LINEBLOCK* compilelet(SCOPE* s, STATEMENT* st);
2021-01-03 14:08:54 -05:00
LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st);
2020-12-31 18:02:04 -05:00
/* END FORWARD DECLARATIONS */
// Miscelaneous
LINE* popthat() {
char* popthat[] = { "pop", "that", "0" };
return mkln(popthat);
}
LINE* pushtemp() {
char* pushtemp[] = { "push", "temp", "0" };
return mkln(pushtemp);
}
char* mkcondlabel(char* name, int count) {
int sz = (strlen(name) + countplaces(count) + 1) * sizeof(char);
char* result = (char*)malloc(sz);
sprintf(result, "%s%i", name, count);
return result;
}
// Handling individual statements
2021-01-06 19:18:52 -05:00
LINEBLOCK* compileret(SCOPE* s, STATEMENT* st) {
TERM* e = st->retstatement;
2020-12-31 18:02:04 -05:00
LINE* ret = onetoken("return");
LINEBLOCK* blk = mklnblk(ret);
// void subroutdecs return 0
if(e == NULL) {
char* tokens[] = { "push", "constant", "0" };
appendlnbefore(blk, mkln(tokens));
} else
2021-01-06 19:18:52 -05:00
blk = mergelnblks(compileexpression(s, st->debug, e), blk);
2020-12-31 18:02:04 -05:00
return blk;
}
2021-01-06 19:18:52 -05:00
LINEBLOCK* compileif(SCOPE* s, STATEMENT* st) {
IFSTATEMENT* ifst = st->ifstatement;
LINEBLOCK* blk = compileexpression(s, st->debug, ifst->base->expression);
2020-12-31 18:02:04 -05:00
2021-01-03 14:08:54 -05:00
pthread_mutex_lock(&(s->compiler->ifmutex));
2020-12-31 18:02:04 -05:00
static int ifcount = 0;
int mycount = ifcount;
ifcount++;
2021-01-03 14:08:54 -05:00
pthread_mutex_unlock(&(s->compiler->ifmutex));
2020-12-31 18:02:04 -05:00
char* truelabel = mkcondlabel("IF_TRUE", mycount);
char* ifgoto[] = { "if-goto", truelabel };
appendln(blk, mkln(ifgoto));
char* falselabel = mkcondlabel("IF_FALSE", mycount);
char* gotofalse[] = { "goto", falselabel };
appendln(blk, mkln(gotofalse));
char* truelabelln[] = { "label", truelabel };
appendln(blk, mkln(truelabelln));
2021-01-06 19:18:52 -05:00
blk = mergelnblks(blk, compilestatements(s, ifst->base->statements));
2020-12-31 18:02:04 -05:00
char* endlabel;
2021-01-06 19:18:52 -05:00
bool haselse = ifst->elsestatements != NULL;
2020-12-31 18:02:04 -05:00
if(haselse) {
endlabel = mkcondlabel("IF_END", mycount);
char* endgoto[] = { "goto", endlabel };
appendln(blk, mkln(endgoto));
}
char* falselabelln[] = { "label", falselabel};
appendln(blk, mkln(falselabelln));
if(haselse) {
2021-01-06 19:18:52 -05:00
blk = mergelnblks(blk, compilestatements(s, ifst->elsestatements));
2020-12-31 18:02:04 -05:00
char* endlabelln[] = { "label", endlabel };
appendln(blk, mkln(endlabelln));
2020-12-31 18:41:22 -05:00
free(endlabel);
2020-12-31 18:02:04 -05:00
}
2020-12-31 18:41:22 -05:00
free(falselabel);
free(truelabel);
2020-12-31 18:02:04 -05:00
return blk;
}
2021-01-06 19:18:52 -05:00
LINEBLOCK* compilewhile(SCOPE* s, STATEMENT* st) {
CONDSTATEMENT* w = st->whilestatement;
LINEBLOCK* blk = compileexpression(s, st->debug, w->expression);
2020-12-31 18:02:04 -05:00
2021-01-03 14:08:54 -05:00
pthread_mutex_lock(&(s->compiler->whilemutex));
2020-12-31 18:02:04 -05:00
static int whilecount = 0;
int mycount = whilecount;
whilecount++;
2021-01-03 14:08:54 -05:00
pthread_mutex_unlock(&(s->compiler->whilemutex));
2020-12-31 18:02:04 -05:00
char* explabel = mkcondlabel("WHILE_EXP", mycount);
char* explabelln[] = { "label", explabel };
appendlnbefore(blk, mkln(explabelln));
appendln(blk, onetoken("not"));
char* endlabel = mkcondlabel("WHILE_END", mycount);
char* ifgoto[] = { "if-goto", endlabel };
appendln(blk, mkln(ifgoto));
2021-01-03 14:08:54 -05:00
blk = mergelnblks(blk, compilestatements(s, w->statements));
2020-12-31 18:02:04 -05:00
char* gotoln[] = { "goto", explabel };
appendln(blk, mkln(gotoln));
char* endlabelln[] = { "label", endlabel };
appendln(blk, mkln(endlabelln));
2020-12-31 18:41:22 -05:00
free(explabel);
free(endlabel);
2020-12-31 18:02:04 -05:00
return blk;
}
2021-01-06 19:18:52 -05:00
LINEBLOCK* compilelet(SCOPE* s, STATEMENT* st) {
LETSTATEMENT* l = st->letstatement;
LINEBLOCK* blk = compileexpression(s, st->debug, l->expression);
2020-12-31 18:02:04 -05:00
if(l->arrayind != NULL) {
appendlnbefore(blk, onetoken("add"));
2021-01-06 19:18:52 -05:00
appendlnbefore(blk, pushvar(s, st->debug, l->varname));
blk = mergelnblks(compileexpression(s, st->debug, l->arrayind), blk);
2020-12-31 18:02:04 -05:00
appendln(blk, poptemp());
appendln(blk, popthatadd());
appendln(blk, pushtemp());
appendln(blk, popthat());
}
else
2021-01-06 19:18:52 -05:00
appendln(blk, popvar(s, st->debug, l->varname));
2020-12-31 18:02:04 -05:00
return blk;
}
2021-01-03 14:08:54 -05:00
LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st) {
2020-12-31 18:02:04 -05:00
s->currdebug = st->debug;
if(st->type == dostatement) return compilesubroutcall(s, st->dostatement);
2021-01-06 19:18:52 -05:00
if(st->type == returnstatement) return compileret(s, st);
if(st->type == ifstatement) return compileif(s, st);
if(st->type == whilestatement) return compilewhile(s, st);
return compilelet(s, st);
2020-12-31 18:02:04 -05:00
}
2021-01-03 14:08:54 -05:00
LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) {
2020-12-31 18:02:04 -05:00
LINEBLOCK* head = NULL;
while(sts != NULL) {
2021-01-03 14:08:54 -05:00
head = mergelnblks(head, compilestatement(s, sts));
2020-12-31 18:02:04 -05:00
sts = sts->next;
}
return head;
}