From b49d0f18687bae9f0f7c403179c1b3e97269eaa7 Mon Sep 17 00:00:00 2001 From: Augusto Gunsch Date: Sun, 27 Dec 2020 18:52:28 -0300 Subject: [PATCH] Improve compiling engine --- compiler/compiler-scopes.c | 308 ++++++++++++++++++++++-------------- compiler/compiler-scopes.h | 42 ++--- compiler/compiler.c | 286 +++++++++++++++++++++------------ parser/parser-expressions.c | 3 +- parser/parser-statements.c | 19 ++- parser/parser-structure.c | 22 +-- parser/parser-tree.h | 5 +- util.h | 2 +- 8 files changed, 416 insertions(+), 271 deletions(-) diff --git a/compiler/compiler-scopes.c b/compiler/compiler-scopes.c index 3e1a138..ed0754c 100644 --- a/compiler/compiler-scopes.c +++ b/compiler/compiler-scopes.c @@ -3,34 +3,34 @@ #include #include "compiler-scopes.h" -// Error messages -void doubledeclaration(const char* name, OBJ* o1, OBJ* o2); -void ensurenoduplicate(SCOPE* s, OBJ* o); +typedef enum { local, staticseg, arg, fieldseg } MEMSEGMENT; +char* memsegnames[] = { "local", "static", "argument", "this" }; -// Generic getters -OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname); -OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type); +// Error messages +void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2); +void ensurenoduplicate(SCOPE* s, char* name); + +// Getters +VAR* getvarinvars(VAR* vars, const char* name); +CLASS* getclass(SCOPE* s, const char* name); +SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name); +SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call); +SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call); +SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call); +SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call); +SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name); // Scope adding +VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg); +void addvar(SCOPE* s, VAR** dest, VAR* v); +void addlocalvar(SCOPE* s, VARDEC* v); void addclassvardec(SCOPE* s, CLASSVARDEC* v); -void addvardec(SCOPE* s, VARDEC* v); -void addsubroutdec(SCOPE* s, SUBROUTDEC* sd); -void addclass(SCOPE* s, CLASS* c); - -// OBJ handling - -VARDEC* tovardec(OBJ* obj) { - if (obj->type == classvardec) - return ((CLASSVARDEC*)(obj->pointer))->base; - else if (obj->type == vardec) - return (VARDEC*)(obj->pointer); - return NULL; -} +void addparameter(SCOPE* s, PARAMETER* p); // Error messages -void doubledeclaration(const char* name, OBJ* o1, OBJ* o2) { +void doubledeclaration(const char* name, DEBUGINFO* d1, DEBUGINFO* d2) { eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n", - name, o1->debug->file, o1->debug->definedat, o2->debug->file, o2->debug->definedat); + name, d1->file, d1->definedat, d2->file, d2->definedat); exit(1); } @@ -44,158 +44,224 @@ void invalidparent(SUBROUTCALL* call) { exit(1); } -void ensurenoduplicate(SCOPE* s, OBJ* o) { - const char* othername; - OBJ* other = getbynamelist(s, o->names, &othername); - if(other != NULL) - doubledeclaration(othername, o, other); +void ensurenoduplicate(SCOPE* s, char* name) { + VAR* v = getvar(s, name); + if(v != NULL) + doubledeclaration(name, s->currdebug, v->debug); + + CLASS* c = getclass(s, name); + if(c != NULL) + doubledeclaration(name, s->currdebug, c->debug); + + SUBROUTDEC* sr = getsubroutdec(s, name); + if(sr != NULL) + doubledeclaration(name, s->currdebug, sr->debug); } // Scope handling - SCOPE* mkscope(SCOPE* prev) { SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE)); - s->objects = NULL; s->previous = prev; - s->condlabelcount = 0; + s->localvars = NULL; + s->fields = NULL; + s->staticvars = NULL; + s->parameters = NULL; + s->classes = NULL; + s->subroutines = NULL; return s; } -// Single type getters -SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) { - return (SUBROUTDEC*)(getbynamewithtype(s, name, subroutdec)->pointer); +// Getters +VAR* getvarinvars(VAR* vars, const char* name) { + while(vars != NULL) { + if(!strcmp(vars->name, name)) + return vars; + vars = vars->next; + } + return NULL; +} + +VAR* getvar(SCOPE* s, const char* name) { + VAR* var = getvarinvars(s->localvars, name); + if(var != NULL) + return var; + var = getvarinvars(s->parameters, name); + if(var != NULL) + return var; + var = getvarinvars(s->fields, name); + if(var != NULL) + return var; + var = getvarinvars(s->staticvars, name); + if(var != NULL) + return var; + if(s->previous != NULL) + return getvar(s->previous, name); + return NULL; } CLASS* getclass(SCOPE* s, const char* name) { - return (CLASS*)(getbynamewithtype(s, name, class)->pointer); -} - -SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) { - SUBROUTDEC* curr = c->subroutdecs; + CLASS* curr = s->classes; while(curr != NULL) { if(!strcmp(curr->name, name)) return curr; curr = curr->next; } + if(s->previous != NULL) + return getclass(s->previous, name); return NULL; } -SUBROUTDEC* getsubroutdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) { - VARDEC* vd = tovardec(var); - if(vd == NULL || vd->primitive) - invalidparent(call); - CLASS* c = getclass(s, vd->type); - return getsubroutdecfromclass(c, call->name); +SUBROUTDEC* getsubroutdecfromlist(SUBROUTDEC* start, char* name) { + while(start != NULL) { + if(!strcmp(start->name, name)) + return start; + start = start->next; + } + return NULL; } -SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) { - SUBROUTDEC* sd; +SUBROUTDEC* getmethod(SCOPE* s, VAR* parent, SUBROUTCALL* call) { + CLASS* c = getclass(s, parent->type); + SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name); + if(d == NULL) + notdeclared(call->name, call->debug); + if(d->subroutclass == function) { + eprintf("Calling a function as if it were a method; file '%s', line %i\n", call->debug->file, call->debug->definedat); + exit(1); + } + return d; +} - OBJ* parent = getbyname(s, call->parentname); - if(parent == NULL) +SUBROUTDEC* getfunction(SCOPE* s, SUBROUTCALL* call) { + CLASS* c = getclass(s, call->parentname); + if(c == NULL) notdeclared(call->parentname, call->debug); + SUBROUTDEC* d = getsubroutdecfromlist(c->subroutdecs, call->name); + if(d == NULL) + notdeclared(call->name, call->debug); + if(d->subroutclass == method) { + eprintf("Calling a method as if it were a function; file '%s', line %i\n", call->debug->file, call->debug->definedat); + exit(1); + } + return d; +} - if(parent->type == class) - sd = getsubroutdecfromclass(parent->pointer, call->name); - else - sd = getsubroutdecfromvar(s, parent, call); - return sd; +SUBROUTDEC* getsubroutdecwithparent(SCOPE* s, SUBROUTCALL* call) { + VAR* parent = getvar(s, call->parentname); + if(parent != NULL) + return getmethod(s, parent, call); + else + return getfunction(s, call); +} + +SUBROUTDEC* getsubroutdecwithoutparent(SCOPE* s, SUBROUTCALL* call) { + SUBROUTDEC* d = getsubroutdecfromlist(s->currclass->subroutdecs, call->name); + if(d == NULL) + notdeclared(call->name, call->debug); + return d; } SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) { - SUBROUTDEC* sd; if(call->parentname != NULL) - sd = getsubroutdecfromparent(s, call); + return getsubroutdecwithparent(s, call); else - sd = getsubroutdec(s, call->name); - if(sd == NULL) - notdeclared(call->name, call->debug); - return sd; + return getsubroutdecwithoutparent(s, call); } -// Generic getters -OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) { - OBJ* curr = s->objects; +SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) { + SUBROUTDEC* curr = s->subroutines; while(curr != NULL) { - STRINGLIST* currn = curr->names; - while(currn != NULL) { - STRINGLIST* currattempt = names; - while(currattempt != NULL) { - if(!strcmp(currn->content, currattempt->content)) { - *retname = currn->content; - return curr; - } - currattempt = currattempt->next; - } - currn = currn->next; - } + if(!strcmp(curr->name, name)) + return curr; curr = curr->next; } if(s->previous != NULL) - return getbynamelist(s->previous, names, retname); + return getsubroutdec(s->previous, name); return NULL; } - -OBJ* getbyname(SCOPE* s, const char* name) { - STRINGLIST* onename = onestr(name); - const char* dummy; - return getbynamelist(s, onename, &dummy); -} - -OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type) { - OBJ* o = getbyname(s, name); - if(o->type != type) - notdeclared(name, o->debug); - return o; -} - // Scope adding -void addobj(SCOPE* s, OBJ* o) { - ensurenoduplicate(s, o); - o->next = s->objects; - s->objects = o; +VAR* mkvar(char* type, char* name, bool primitive, DEBUGINFO* debug, MEMSEGMENT seg) { + VAR* v = (VAR*)malloc(sizeof(VAR)); + v->name = name; + v->type = type; + v->debug = debug; + v->memsegment = memsegnames[seg]; + v->primitive = primitive; + return v; } -OBJ* mkobj(void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) { - OBJ* o = (OBJ*)malloc(sizeof(OBJ)); - o->pointer = pointer; - o->type = type; - o->debug = debug; - o->names = names; - return o; +void addvar(SCOPE* s, VAR** dest, VAR* v) { + ensurenoduplicate(s, v->name); + + if(!v->primitive) { + CLASS* type = getclass(s, v->type); + if(type == NULL) + notdeclared(v->type, v->debug); + } + + if(*dest == NULL) + v->index = 0; + else + v->index = 1+(*dest)->index; + + v->next = *dest; + *dest = v; } -void addany(SCOPE* s, void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) { - addobj(s, mkobj(pointer, type, debug, names)); +void addlocalvar(SCOPE* s, VARDEC* v) { + STRINGLIST* currname = v->names; + while(currname != NULL) { + addvar(s, &(s->localvars), mkvar(v->type, currname->content, v->primitive, v->debug, local)); + currname = currname->next; + } } -void addclassvardecs(SCOPE* s, CLASSVARDEC* v) { - addany(s, v, classvardec, v->base->debug, v->base->names); - if(v->next != NULL) - addclassvardecs(s, v->next); +void addstaticvar(SCOPE* s, CLASSVARDEC* v) { + STRINGLIST* currname = v->base->names; + while(currname != NULL) { + addvar(s, &(s->staticvars), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, staticseg)); + currname = currname->next; + } } -void addvardecs(SCOPE* s, VARDEC* v) { - addany(s, v, vardec, v->debug, v->names); - if(v->next != NULL) - addvardecs(s, v->next); +void addfield(SCOPE* s, CLASSVARDEC* v) { + STRINGLIST* currname = v->base->names; + while(currname != NULL) { + addvar(s, &(s->fields), mkvar(v->base->type, currname->content, v->base->primitive, v->base->debug, fieldseg)); + currname = currname->next; + } } -void addsubroutdecs(SCOPE* s, SUBROUTDEC* sd) { - addany(s, sd, subroutdec, sd->debug, onestr(sd->name)); - if(sd->next != NULL) - addsubroutdecs(s, sd->next); +void addclassvardec(SCOPE* s, CLASSVARDEC* v) { + if(v->type == staticseg) + addstaticvar(s, v); + else + addfield(s, v); } -void addclasses(SCOPE* s, CLASS* c) { - addany(s, c, class, c->debug, onestr(c->name)); - if(c->next != NULL) - addclasses(s, c->next); +void addparameter(SCOPE* s, PARAMETER* p) { + addvar(s, &(s->parameters), mkvar(p->type, p->name, p->primitive, p->debug, arg)); } -void addparameters(SCOPE* s, PARAMETER* p) { - addany(s, p, parameter, p->debug, onestr(p->name)); - if(p->next != NULL) - addparameters(s, p->next); +// Group adding +void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs) { + while(classvardecs != NULL) { + addclassvardec(s, classvardecs); + classvardecs = classvardecs->next; + } +} + +void addlocalvars(SCOPE* s, VARDEC* localvars) { + while(localvars != NULL) { + addlocalvar(s, localvars); + localvars = localvars->next; + } +} + +void addparameters(SCOPE* s, PARAMETER* params) { + while(params != NULL) { + addparameter(s, params); + params = params->next; + } } diff --git a/compiler/compiler-scopes.h b/compiler/compiler-scopes.h index 1c8e893..c72f4ec 100644 --- a/compiler/compiler-scopes.h +++ b/compiler/compiler-scopes.h @@ -9,39 +9,43 @@ * certain semantic rules. */ // Data types -typedef enum { - subroutdec, classvardec, vardec, class, parameter -} OBJTYPE; - -typedef struct object { - void* pointer; +typedef struct var { DEBUGINFO* debug; - STRINGLIST* names; - OBJTYPE type; - struct object* next; -} OBJ; + char* memsegment; + char* type; + char* name; + int index; + bool primitive; + struct var* next; +} VAR; typedef struct scope { - OBJ* objects; - int condlabelcount; + DEBUGINFO* currdebug; + CLASS* currclass; + + CLASS* classes; + SUBROUTDEC* subroutines; + + VAR* fields; + VAR* staticvars; + VAR* localvars; + VAR* parameters; + struct scope* previous; } SCOPE; // Group adding -void addclassvardecs(SCOPE* s, CLASSVARDEC* vs); -void addvardecs(SCOPE* s, VARDEC* vs); -void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss); -void addclasses(SCOPE* s, CLASS* c); -void addparameters(SCOPE* s, PARAMETER* p); +void addclassvardecs(SCOPE* s, CLASSVARDEC* classvardecs); +void addlocalvars(SCOPE* s, VARDEC* localvars); +void addparameters(SCOPE* s, PARAMETER* params); // Scope handling SCOPE* mkscope(SCOPE* prev); // Single type getters -SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name); SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call); CLASS* getclass(SCOPE* s, const char* name); // Generic getters -OBJ* getbyname(SCOPE* s, const char* name); +VAR* getvar(SCOPE* s, const char* name); #endif diff --git a/compiler/compiler.c b/compiler/compiler.c index 9fd90e2..f4c50ae 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -2,9 +2,11 @@ #include #include "compiler.h" -LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts); +LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts); +LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call); +LINEBLOCK* compileexpression(SCOPE* s, TERM* e); -int countparameters(EXPRESSIONLIST* params) { +int countparameters(PARAMETER* params) { int i = 0; while(params != NULL) { i++; @@ -13,10 +15,23 @@ int countparameters(EXPRESSIONLIST* params) { return i; } +int countexpressions(EXPRESSIONLIST* explist) { + int i = 0; + while(explist != NULL) { + i++; + explist = explist->next; + } + return i; +} + int countlocalvars(VARDEC* decs) { int i = 0; while(decs != NULL) { - i++; + STRINGLIST* curr = decs->names; + while(curr != NULL) { + i++; + curr = curr->next; + } decs = decs->next; } return i; @@ -29,10 +44,11 @@ char* dotlabel(char* n1, char* n2) { return result; } -char* mkcondlabel(SCOPE* s) { - char* label = dotlabel("cond-label", itoa(s->condlabelcount)); - s->condlabelcount++; - return label; +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; } LINE* onetoken(char* str) { @@ -75,50 +91,94 @@ LINE* mathopln(char op) { } } -LINEBLOCK* compileexpression(SCOPE* s, TERM* e) { - LINEBLOCK* myblk; - LINEBLOCK* next = NULL; - - if(e->type == intconstant) { - char* tokens[] = { "push", "constant", itoa(e->integer) }; - myblk = mklnblk(mksimpleln(tokens, strcount(tokens))); - } - else if(e->type == unaryopterm) { - myblk = compileexpression(s, e->expression); - LINE* neg = onetoken("neg"); - appendln(myblk, neg); - } - else if(e->type == innerexpression) { - myblk = compileexpression(s, e->expression); - } - else if(e->type == varname) { - eprintf("TO BE IMPLEMENTED\n"); - exit(1); - } - else { - eprintf("Unsupported term yet %i\n", e->type); - exit(1); - } - - if(e->next != NULL) { - next = compileexpression(s, e->next); - appendln(next, mathopln(e->op)); - myblk = mergelnblks(myblk, next); - } - - return myblk; +LINEBLOCK* pushconstant(int n) { + char* tokens[] = { "push", "constant", itoa(n) }; + return mklnblk(mksimpleln(tokens, strcount(tokens))); } -LINEBLOCK* compileparameters(SCOPE* s, EXPRESSIONLIST* params) { +LINEBLOCK* pushunaryopterm(SCOPE* s, TERM* t) { + LINEBLOCK* blk = compileexpression(s, t->expression); + LINE* neg; + if(t->unaryop == '-') + neg = onetoken("neg"); + else + neg = onetoken("not"); + appendln(blk, neg); + return blk; +} + +LINEBLOCK* opvar(SCOPE* s, char* op, const char* name) { + VAR* v = getvar(s, name); + char* tokens[] = { op, v->memsegment, itoa(v->index) }; + return mklnblk(mksimpleln(tokens, strcount(tokens))); + +} + +LINEBLOCK* pushvar(SCOPE* s, const char* name) { + return opvar(s, "push", name); +} + +LINEBLOCK* popvar(SCOPE* s, const char* name) { + return opvar(s, "pop", name); +} + +LINEBLOCK* pushfalse() { + return pushconstant(0); +} + +LINEBLOCK* pushtrue() { + LINEBLOCK* blk = pushfalse(); + appendln(blk, onetoken("not")); + return blk; +} + +LINEBLOCK* compilekeywordconst(SCOPE* s, TERM* t) { + if(!strcmp(t->string, "true")) return pushtrue(); + if(!strcmp(t->string, "false")) return pushfalse(); + eprintf("Unsupported keyword '%s'\n", t->string); + exit(1); +} + +LINEBLOCK* compileterm(SCOPE* s, TERM* t) { + if(t->type == intconstant) return pushconstant(t->integer); + if(t->type == unaryopterm) return pushunaryopterm(s, t); + if(t->type == innerexpression) return compileexpression(s, t->expression); + if(t->type == varname) return pushvar(s, t->string); + if(t->type == subroutcall) return compilesubroutcall(s, t->call); + if(t->type == keywordconstant) return compilekeywordconst(s, t); + else { + eprintf("Unsupported term yet %i\n", t->type); + exit(1); + } +} + +LINEBLOCK* compileexpression(SCOPE* s, TERM* e) { + LINEBLOCK* blk = compileterm(s, e); + TERM* curr = e->next; + if(curr != NULL) { + while(true) { + blk = mergelnblks(blk, compileterm(s, curr)); + if(curr->next != NULL) { + appendln(blk, mathopln(curr->op)); + curr = curr->next; + } + else break; + } + appendln(blk, mathopln(e->op)); + } + return blk; +} + +LINEBLOCK* compileexplist(SCOPE* s, EXPRESSIONLIST* explist) { LINEBLOCK* head = NULL; - while(params != NULL) { - head = mergelnblks(head, compileexpression(s, params->expression)); - params = params->next; + while(explist != NULL) { + head = mergelnblks(head, compileexpression(s, explist->expression)); + explist = explist->next; } return head; } -LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) { +LINEBLOCK* compilecallln(SCOPE* s, SUBROUTCALL* call) { LINE* ln = mkline(3); addtoken(ln, ezheapstr("call")); @@ -126,24 +186,24 @@ LINEBLOCK* compilecallln(CLASS* c, SUBROUTCALL* call) { if(call->parentname != NULL) addtoken(ln, dotlabel(call->parentname, call->name)); else - addtoken(ln, dotlabel(c->name, call->name)); + addtoken(ln, dotlabel(s->currclass->name, call->name)); - addtoken(ln, itoa(countparameters(call->parameters))); + addtoken(ln, itoa(countexpressions(call->parameters))); return mklnblk(ln); } // temporary ignore list for OS functions char* ignoresubroutdecs[] = { - "printInt", "void", "peek", "int" + "printInt", "void", "peek", "int", "poke", "void" }; int ignorecount = sizeof(ignoresubroutdecs) / sizeof(char*); -LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) { - LINEBLOCK* block = compilecallln(c, call); +LINEBLOCK* compilesubroutcall(SCOPE* s, SUBROUTCALL* call) { + LINEBLOCK* blk = compilecallln(s, call); if(call->parameters != NULL) - block = mergelnblks(compileparameters(s, call->parameters), block); + blk = mergelnblks(compileexplist(s, call->parameters), blk); // void functions always return 0 // therefore must be thrown away @@ -160,97 +220,117 @@ LINEBLOCK* compilesubroutcall(SCOPE* s, CLASS* c, SUBROUTCALL* call) { type = getsubroutdecfromcall(s, call)->type; if(!strcmp(type, "void")) { char* tokens[] = { "pop", "temp", "0" }; - appendln(block, mksimpleln(tokens, sizeof(tokens) / sizeof(char*))); + appendln(blk, mksimpleln(tokens, sizeof(tokens) / sizeof(char*))); } - return block; + return blk; } LINEBLOCK* compileret(SCOPE* s, TERM* e) { LINE* ret = onetoken("return"); - LINEBLOCK* block = mklnblk(ret); + LINEBLOCK* blk = mklnblk(ret); // void subroutdecs return 0 if(e == NULL) { char* tokens[] = { "push", "constant", "0" }; - appendlnbefore(block, mksimpleln(tokens, strcount(tokens))); + appendlnbefore(blk, mksimpleln(tokens, strcount(tokens))); } else - block = mergelnblks(compileexpression(s, e), block); + blk = mergelnblks(compileexpression(s, e), blk); - return block; + return blk; } -LINEBLOCK* compileif(SCOPE* s, CLASS* c, IFSTATEMENT* st) { - LINEBLOCK* block = compileexpression(s, st->base->expression); - appendln(block, onetoken("not")); +LINEBLOCK* compileif(SCOPE* s, IFSTATEMENT* st) { + LINEBLOCK* blk = compileexpression(s, st->base->expression); + + static int ifcount = 0; + int mycount = ifcount; + ifcount++; - char* label1 = mkcondlabel(s); - char* ifgoto[] = { "if-goto", label1 }; - appendln(block, mksimpleln(ifgoto, strcount(ifgoto))); + char* truelabel = mkcondlabel("IF_TRUE", mycount); + char* ifgoto[] = { "if-goto", truelabel }; + appendln(blk, mksimpleln(ifgoto, strcount(ifgoto))); + + char* falselabel = mkcondlabel("IF_FALSE", mycount); + char* gotofalse[] = { "goto", falselabel }; + appendln(blk, mksimpleln(gotofalse, strcount(gotofalse))); - block = mergelnblks(block, compilestatements(s, c, st->base->statements)); + char* truelabelln[] = { "label", truelabel }; + appendln(blk, mksimpleln(truelabelln, strcount(truelabelln))); - char* label2; + blk = mergelnblks(blk, compilestatements(s, st->base->statements)); + + char* endlabel; bool haselse = st->elsestatements != NULL; if(haselse) { - char* label2 = mkcondlabel(s); - char* gotoln[] = { "goto", label2 }; - appendln(block, mksimpleln(gotoln, strcount(gotoln))); + endlabel = mkcondlabel("IF_END", mycount); + char* endgoto[] = { "goto", endlabel }; + appendln(blk, mksimpleln(endgoto, strcount(endgoto))); } - char* label1ln[] = { "label", label1 }; - appendln(block, mksimpleln(label1ln, strcount(label1ln))); + char* falselabelln[] = { "label", falselabel}; + appendln(blk, mksimpleln(falselabelln, strcount(falselabelln))); if(haselse) { - block = mergelnblks(block, compilestatements(s, c, st->elsestatements)); - char* label2ln[] = { "label", label2 }; - appendln(block, mksimpleln(label2ln, strcount(label2ln))); + blk = mergelnblks(blk, compilestatements(s, st->elsestatements)); + char* endlabelln[] = { "label", endlabel }; + appendln(blk, mksimpleln(endlabelln, strcount(endlabelln))); } - return block; + + return blk; } -LINEBLOCK* compilewhile(SCOPE* s, CLASS* c, CONDSTATEMENT* w) { - LINEBLOCK* block = compileexpression(s, w->expression); +LINEBLOCK* compilewhile(SCOPE* s, CONDSTATEMENT* w) { + LINEBLOCK* blk = compileexpression(s, w->expression); - char* label1 = mkcondlabel(s); - char* label1ln[] = { "label", label1 }; - appendlnbefore(block, mksimpleln(label1ln, strcount(label1ln))); + static int whilecount = 0; + int mycount = whilecount; + whilecount++; - appendln(block, onetoken("not")); + char* explabel = mkcondlabel("WHILE_EXP", mycount); + char* explabelln[] = { "label", explabel }; + appendlnbefore(blk, mksimpleln(explabelln, strcount(explabelln))); - char* label2 = mkcondlabel(s); - char* ifgoto[] = { "if-goto", label2 }; - appendln(block, mksimpleln(ifgoto, strcount(ifgoto))); + appendln(blk, onetoken("not")); - block = mergelnblks(block, compilestatements(s, c, w->statements)); + char* endlabel = mkcondlabel("WHILE_END", mycount); + char* ifgoto[] = { "if-goto", endlabel }; + appendln(blk, mksimpleln(ifgoto, strcount(ifgoto))); - char* gotoln[] = { "goto", label1 }; - appendln(block, mksimpleln(gotoln, strcount(gotoln))); + blk = mergelnblks(blk, compilestatements(s, w->statements)); - char* label2ln[] = { "label", label2 }; - appendln(block, mksimpleln(label2ln, strcount(label2ln))); + char* gotoln[] = { "goto", explabel }; + appendln(blk, mksimpleln(gotoln, strcount(gotoln))); - return block; + char* endlabelln[] = { "label", endlabel }; + appendln(blk, mksimpleln(endlabelln, strcount(endlabelln))); + + return blk; } -LINEBLOCK* compilelet(SCOPE* s, CLASS* c, LETSTATEMENT* l) { +LINEBLOCK* compilelet(SCOPE* s, LETSTATEMENT* l) { + // missing array ind + LINEBLOCK* blk = compileexpression(s, l->expression); + blk = mergelnblks(blk, popvar(s, l->varname)); + return blk; } -LINEBLOCK* compilestatement(SCOPE* s, CLASS* c, STATEMENT* st) { - if(st->type == dostatement) return compilesubroutcall(s, c, st->dostatement); +LINEBLOCK* compilestatement(SCOPE* s, STATEMENT* st) { + s->currdebug = st->debug; + if(st->type == dostatement) return compilesubroutcall(s, 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); + if(st->type == ifstatement) return compileif(s, st->ifstatement); + if(st->type == whilestatement) return compilewhile(s, st->whilestatement); + if(st->type == letstatement) return compilelet(s, st->letstatement); eprintf("UNSUPPORTED type %i\n", st->type); exit(1); } -LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) { +LINEBLOCK* compilestatements(SCOPE* s, STATEMENT* sts) { LINEBLOCK* head = NULL; while(sts != NULL) { - head = mergelnblks(head, compilestatement(s, c, sts)); + head = mergelnblks(head, compilestatement(s, sts)); sts = sts->next; } return head; @@ -258,9 +338,10 @@ LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) { LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) { SCOPE* myscope = mkscope(s); + myscope->currclass = c; if(b->vardecs != NULL) - addvardecs(s, b->vardecs); - LINEBLOCK* head = compilestatements(myscope, c, b->statements); + addlocalvars(s, b->vardecs); + LINEBLOCK* head = compilestatements(myscope, b->statements); return head; } @@ -287,8 +368,11 @@ LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) { // types: method, function, constructor // must switch all of these + SCOPE* myscope = mkscope(s); + if(sd->parameters != NULL) + addparameters(myscope, sd->parameters); if(sd->subroutclass == function) - return compilefundec(s, c, sd); + return compilefundec(myscope, c, sd); } LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { @@ -296,7 +380,7 @@ LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { if(class->vardecs != NULL) addclassvardecs(topscope, class->vardecs); if(class->subroutdecs != NULL) - addsubroutdecs(topscope, class->subroutdecs); + topscope->subroutines = class->subroutdecs; LINEBLOCK* output = NULL; SUBROUTDEC* curr = class->subroutdecs; @@ -320,7 +404,7 @@ void compile(COMPILER* c) { COMPILER* mkcompiler(CLASS* classes) { COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER)); c->globalscope = mkscope(NULL); - addclasses(c->globalscope, classes); + c->globalscope->classes = classes; c->classes = classes; return c; } diff --git a/parser/parser-expressions.c b/parser/parser-expressions.c index 27ef932..55c6be0 100644 --- a/parser/parser-expressions.c +++ b/parser/parser-expressions.c @@ -73,6 +73,7 @@ TERM* parsekeyword(PARSER* p) { TERM* parseunaryopterm(PARSER* p) { TERM* t = mkterm(unaryopterm); + t->unaryop = p->current->token[0]; next(p); t->expression = parseterm(p); t->expression->next = NULL; @@ -92,7 +93,7 @@ TERM* parsecalltermnullified(PARSER* p) { if(call == NULL) return NULL; TERM* t = mkterm(subroutcall); - t->call == call; + t->call = call; return t; } diff --git a/parser/parser-statements.c b/parser/parser-statements.c index 97c0efc..3bf1019 100644 --- a/parser/parser-statements.c +++ b/parser/parser-statements.c @@ -3,7 +3,7 @@ #include "parser-internal.h" #include "parser-statements.h" -STATEMENT* mkstatement(STATEMENTTYPE t); +STATEMENT* mkstatement(PARSER* p, STATEMENTTYPE t); STATEMENT* parsestatementnullified(PARSER* p); STATEMENT* parselet(PARSER* p); CONDSTATEMENT* parsecond(PARSER* p); @@ -12,9 +12,10 @@ STATEMENT* parsewhile(PARSER* p); STATEMENT* parsedo(PARSER* p); STATEMENT* parsereturn(PARSER* p); -STATEMENT* mkstatement(STATEMENTTYPE t) { +STATEMENT* mkstatement(PARSER* p, STATEMENTTYPE t) { STATEMENT* s = (STATEMENT*)malloc(sizeof(STATEMENT)); s->type = t; + s->debug = getdebug(p); return s; } @@ -43,8 +44,8 @@ STATEMENT* parsestatements(PARSER* p) { STATEMENT* parselet(PARSER* p) { next(p); - STATEMENT* s = mkstatement(letstatement); - LETSTATEMENT* letst= (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT)); + STATEMENT* s = mkstatement(p, letstatement); + LETSTATEMENT* letst = (LETSTATEMENT*)malloc(sizeof(LETSTATEMENT)); letst->varname = parseidentifier(p); @@ -63,6 +64,7 @@ STATEMENT* parselet(PARSER* p) { checkcontent(p, ";"); s->type = letstatement; + s->letstatement = letst; return s; } @@ -84,7 +86,7 @@ CONDSTATEMENT* parsecond(PARSER* p) { STATEMENT* parseif(PARSER* p) { next(p); - STATEMENT* s = mkstatement(ifstatement); + STATEMENT* s = mkstatement(p, ifstatement); IFSTATEMENT* ifst = (IFSTATEMENT*)malloc(sizeof(IFSTATEMENT)); ifst->base = parsecond(p); @@ -99,12 +101,13 @@ STATEMENT* parseif(PARSER* p) { ifst->elsestatements = NULL; s->type = ifstatement; + s->ifstatement = ifst; return s; } STATEMENT* parsewhile(PARSER* p) { next(p); - STATEMENT* s = mkstatement(whilestatement); + STATEMENT* s = mkstatement(p, whilestatement); s->whilestatement = parsecond(p); return s; @@ -112,7 +115,7 @@ STATEMENT* parsewhile(PARSER* p) { STATEMENT* parsedo(PARSER* p) { next(p); - STATEMENT* s = mkstatement(dostatement); + STATEMENT* s = mkstatement(p, dostatement); s->dostatement = parsesubroutcall(p); @@ -122,7 +125,7 @@ STATEMENT* parsedo(PARSER* p) { STATEMENT* parsereturn(PARSER* p) { next(p); - STATEMENT* s = mkstatement(returnstatement); + STATEMENT* s = mkstatement(p, returnstatement); s->retstatement = parseexpressionnullified(p); diff --git a/parser/parser-structure.c b/parser/parser-structure.c index 92f3cf6..6dff980 100644 --- a/parser/parser-structure.c +++ b/parser/parser-structure.c @@ -60,7 +60,7 @@ CLASS* parseclasses(PARSER* p) { int parsepossibilities(PARSER* p, STRINGARRAY* poss) { for(int i = 0; i < poss->size; i++) - if(!strcmp(p->current->token, poss->items[i])) + if(equals(p, poss->items[i])) return i; return -1; } @@ -87,14 +87,9 @@ CLASSVARDEC* parseclassvardec(PARSER* p) { CLASSVARDEC* parseclassvardecs(PARSER* p) { CLASSVARDEC* head = parseclassvardec(p); - if(head != NULL) - head->base->index = 0; - int index = 1; CLASSVARDEC* curr = head; CLASSVARDEC* nextc; while(nextc = parseclassvardec(p), nextc != NULL) { - nextc->base->index = index; - index++; curr->next = nextc; curr = nextc; } @@ -156,6 +151,7 @@ PARAMETER* parseparameter(PARSER* p) { if(equals(p, ")")) return NULL; param->debug = getdebug(p); + param->primitive = isprimitive(p->current); param->type = parsetype(p); param->name = parseidentifier(p); return param; @@ -163,9 +159,6 @@ PARAMETER* parseparameter(PARSER* p) { PARAMETER* parseparameters(PARSER* p) { PARAMETER* head = parseparameter(p); - if(head != NULL) - head->index = 0; - int index = 1; PARAMETER* curr = head; PARAMETER* nextp; while(equals(p, ",")) { @@ -173,9 +166,7 @@ PARAMETER* parseparameters(PARSER* p) { nextp = parseparameter(p); if(nextp == NULL) unexpected(p); - nextp->index = index; curr->next = nextp; - index++; curr = curr->next; } if(curr != NULL) @@ -199,7 +190,7 @@ bool isprimitive(TOKEN* tk) { } char* parsetype(PARSER* p) { - if(p->current->type != identifier) + if(p->current->type != identifier && p->current->type != keyword) unexpected(p); char* result = p->current->token; @@ -246,15 +237,10 @@ VARDEC* parsevardec(PARSER* p) { VARDEC* parsevardecs(PARSER* p) { VARDEC* head = parsevardec(p); - if(head != NULL) - head->index = 0; - int index = 1; VARDEC* curr = head; VARDEC* nextv; while(nextv = parsevardec(p), nextv != NULL) { - nextv->index = index; - index++; - curr->next = nextv; + curr->next = nextv; curr = nextv; } if(curr != NULL) diff --git a/parser/parser-tree.h b/parser/parser-tree.h index 0f758fd..ec80b35 100644 --- a/parser/parser-tree.h +++ b/parser/parser-tree.h @@ -60,7 +60,7 @@ typedef struct subroutdec { typedef struct parameter { char* type; char* name; - int index; + bool primitive; DEBUGINFO* debug; struct parameter* next; } PARAMETER; @@ -73,7 +73,6 @@ typedef struct subroutbody { typedef struct vardec { char* type; bool primitive; - int index; TOKENTYPE typeclass; STRINGLIST* names; DEBUGINFO* debug; @@ -94,6 +93,7 @@ typedef struct statement { struct subroutcall* dostatement; struct term* retstatement; }; + DEBUGINFO* debug; struct statement* next; } STATEMENT; @@ -129,6 +129,7 @@ typedef struct term { }; struct term* arrayexp; char op; + char unaryop; struct term* next; } TERM; diff --git a/util.h b/util.h index 85e1f6d..4e62c1f 100644 --- a/util.h +++ b/util.h @@ -13,7 +13,7 @@ #define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) } typedef struct stringlist { - const char* content; + char* content; struct stringlist* next; } STRINGLIST;