Add 'if' and 'while' support

This commit is contained in:
Augusto Gunsch 2020-12-22 15:45:12 -03:00
parent d65bcc202f
commit 02fc8307a4
No known key found for this signature in database
GPG Key ID: F7EEFE29825C72DC
3 changed files with 78 additions and 12 deletions

View File

@ -116,6 +116,7 @@ SCOPE* mkscope(SCOPE* prev) {
s->vardecs = NULL; s->vardecs = NULL;
s->classes = NULL; s->classes = NULL;
s->previous = prev; s->previous = prev;
s->condlabelcount = 0;
return s; return s;
} }

View File

@ -14,6 +14,7 @@ typedef struct scope {
CLASSVARDEC* classvardecs; CLASSVARDEC* classvardecs;
VARDEC* vardecs; VARDEC* vardecs;
CLASS* classes; CLASS* classes;
int condlabelcount;
struct scope* previous; struct scope* previous;
} SCOPE; } SCOPE;

View File

@ -2,6 +2,8 @@
#include <string.h> #include <string.h>
#include "compiler.h" #include "compiler.h"
LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts);
int countparameters(EXPRESSIONLIST* params) { int countparameters(EXPRESSIONLIST* params) {
int i = 0; int i = 0;
while(params != NULL) { while(params != NULL) {
@ -27,8 +29,10 @@ char* dotlabel(char* n1, char* n2) {
return result; return result;
} }
char* subroutdecname(CLASS* c, SUBROUTDEC* sd) { char* mkcondlabel(SCOPE* s) {
return dotlabel(c->name, sd->name); char* label = dotlabel("cond-label", itoa(s->condlabelcount));
s->condlabelcount++;
return label;
} }
LINE* onetoken(char* str) { LINE* onetoken(char* str) {
@ -87,6 +91,10 @@ LINEBLOCK* compileexpression(SCOPE* s, TERM* e) {
else if(e->type == innerexpression) { else if(e->type == innerexpression) {
myblk = compileexpression(s, e->expression); myblk = compileexpression(s, e->expression);
} }
else if(e->type == varname) {
eprintf("TO BE IMPLEMENTED\n");
exit(1);
}
else { else {
eprintf("Unsupported term yet %i\n", e->type); eprintf("Unsupported term yet %i\n", e->type);
exit(1); exit(1);
@ -165,22 +173,78 @@ LINEBLOCK* compileret(SCOPE* s, TERM* e) {
// void subroutdecs return 0 // void subroutdecs return 0
if(e == NULL) { if(e == NULL) {
char* tokens[] = { "push", "constant", "0" }; char* tokens[] = { "push", "constant", "0" };
appendlnbefore(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*))); appendlnbefore(block, mksimpleln(tokens, strcount(tokens)));
} else } else
block = mergelnblks(compileexpression(s, e), block); block = mergelnblks(compileexpression(s, e), block);
return block; return block;
} }
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) { LINEBLOCK* compileif(SCOPE* s, CLASS* c, IFSTATEMENT* st) {
if(st->type == dostatement) LINEBLOCK* block = compileexpression(s, st->base->expression);
return compilesubroutcall(s, c, st->dostatement); appendln(block, onetoken("not"));
else if(st->type == returnstatement)
return compileret(s, st->retstatement); char* label1 = mkcondlabel(s);
else { char* ifgoto[] = { "if-goto", label1 };
eprintf("UNSUPPORTED\n"); appendln(block, mksimpleln(ifgoto, strcount(ifgoto)));
exit(1);
block = mergelnblks(block, compilestatements(s, c, st->base->statements));
char* label2;
bool haselse = st->elsestatements != NULL;
if(haselse) {
char* label2 = mkcondlabel(s);
char* gotoln[] = { "goto", label2 };
appendln(block, mksimpleln(gotoln, strcount(gotoln)));
} }
char* label1ln[] = { "label", label1 };
appendln(block, mksimpleln(label1ln, strcount(label1ln)));
if(haselse) {
block = mergelnblks(block, compilestatements(s, c, st->elsestatements));
char* label2ln[] = { "label", label2 };
appendln(block, mksimpleln(label2ln, strcount(label2ln)));
}
return block;
}
LINEBLOCK* compilewhile(SCOPE* s, CLASS* c, CONDSTATEMENT* w) {
LINEBLOCK* block = compileexpression(s, w->expression);
char* label1 = mkcondlabel(s);
char* label1ln[] = { "label", label1 };
appendlnbefore(block, mksimpleln(label1ln, strcount(label1ln)));
appendln(block, onetoken("not"));
char* label2 = mkcondlabel(s);
char* ifgoto[] = { "if-goto", label2 };
appendln(block, mksimpleln(ifgoto, strcount(ifgoto)));
block = mergelnblks(block, compilestatements(s, c, w->statements));
char* gotoln[] = { "goto", label1 };
appendln(block, mksimpleln(gotoln, strcount(gotoln)));
char* label2ln[] = { "label", label2 };
appendln(block, mksimpleln(label2ln, strcount(label2ln)));
return block;
}
LINEBLOCK* compilelet(SCOPE* s, CLASS* c, LETSTATEMENT* l) {
}
LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) {
if(st->type == dostatement) return compilesubroutcall(s, c, st->dostatement);
if(st->type == returnstatement) return compileret(s, st->retstatement);
if(st->type == ifstatement) return compileif(s, c, st->ifstatement);
if(st->type == whilestatement) return compilewhile(s, c, st->whilestatement);
if(st->type == letstatement) return compilelet(s, c, st->letstatement);
eprintf("UNSUPPORTED type %i\n", st->type);
exit(1);
} }
LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) { LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) {
@ -201,7 +265,7 @@ LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) {
LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) { LINEBLOCK* compilefundec(SCOPE* s, CLASS* c, SUBROUTDEC* f) {
LINE* label = mkline(3); LINE* label = mkline(3);
addtoken(label, ezheapstr("function")); addtoken(label, ezheapstr("function"));
addtoken(label, subroutdecname(c, f)); addtoken(label, dotlabel(c->name, f->name));
addtoken(label, itoa(countlocalvars(f->body->vardecs))); addtoken(label, itoa(countlocalvars(f->body->vardecs)));
label->next = NULL; label->next = NULL;