diff --git a/compiler/compiler-scopes.c b/compiler/compiler-scopes.c index 89cd93a..3e1a138 100644 --- a/compiler/compiler-scopes.c +++ b/compiler/compiler-scopes.c @@ -3,25 +3,13 @@ #include #include "compiler-scopes.h" -// INTERNAL FUNCTIONS -// Information gathering -bool existstr(STRINGLIST* strs, const char* str); -bool existclass(CLASS* c, const char* name); -DEBUGINFO* getdebuginfo(OBJ* obj); - // Error messages -void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other); -void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug); - -// Scope handling -void popscope(SCOPE** s); // may be removed - -// Single type getters -VARDEC* getvardec(SCOPE* s, const char* name); -CLASSVARDEC* getclassvardec(SCOPE* s, const char* name); +void doubledeclaration(const char* name, OBJ* o1, OBJ* o2); +void ensurenoduplicate(SCOPE* s, OBJ* o); // Generic getters OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname); +OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type); // Scope adding void addclassvardec(SCOPE* s, CLASSVARDEC* v); @@ -29,58 +17,20 @@ void addvardec(SCOPE* s, VARDEC* v); void addsubroutdec(SCOPE* s, SUBROUTDEC* sd); void addclass(SCOPE* s, CLASS* c); -// DEFINITIONS -// Information gathering -bool existstr(STRINGLIST* strs, const char* str) { - while(strs != NULL) { - if(!strcmp(strs->content, str)) - return true; - strs = strs->next; - } - return false; -} - -bool existclass(CLASS* c, const char* name) { - while(c != NULL) { - if(!strcmp(c->name, name)) - return true; - c = c->next; - } - return false; -} - // OBJ handling -DEBUGINFO* getdebugclassvardec(OBJ* obj) { - return obj->classvardec->base->debug; -} - -DEBUGINFO* getdebugvardec(OBJ* obj) { - return obj->vardec->debug; -} - -DEBUGINFO* getdebugsubroutdec(OBJ* obj) { - return obj->subroutdec->debug; -} - -DEBUGINFO* getdebugclass(OBJ* obj) { - return obj->class->debug; -} - VARDEC* tovardec(OBJ* obj) { if (obj->type == classvardec) - return obj->classvardec->base; + return ((CLASSVARDEC*)(obj->pointer))->base; else if (obj->type == vardec) - return obj->vardec; + return (VARDEC*)(obj->pointer); return NULL; } // Error messages - -void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other) { - DEBUGINFO* debugother = other->getdebug(other); +void doubledeclaration(const char* name, OBJ* o1, OBJ* o2) { eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n", - name, debug->file, debug->definedat, debugother->file, debugother->definedat); + name, o1->debug->file, o1->debug->definedat, o2->debug->file, o2->debug->definedat); exit(1); } @@ -94,85 +44,30 @@ void invalidparent(SUBROUTCALL* call) { exit(1); } -void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug) { - OBJ* other = getbyname(s, name); - if(other != NULL) - doubledeclaration(name, debug, other); -} - -void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) { +void ensurenoduplicate(SCOPE* s, OBJ* o) { const char* othername; - OBJ* other = getbynamelist(s, names, &othername); + OBJ* other = getbynamelist(s, o->names, &othername); if(other != NULL) - doubledeclaration(othername, debug, other); + doubledeclaration(othername, o, other); } // Scope handling SCOPE* mkscope(SCOPE* prev) { SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE)); - s->subroutines = NULL; - s->classvardecs = NULL; - s->vardecs = NULL; - s->classes = NULL; + s->objects = NULL; s->previous = prev; s->condlabelcount = 0; return s; } -void popscope(SCOPE** s) { // might be useless - SCOPE* prev = (*s)->previous; - free(*s); - (*s) = prev; -} - // Single type getters -VARDEC* getvardec(SCOPE* s, const char* name) { - VARDEC* curr = s->vardecs; - while(curr != NULL) { - if(existstr(curr->names, name)) - return curr; - curr = curr->next; - } - if(s->previous != NULL) - return getvardec(s->previous, name); - return NULL; -} - -CLASSVARDEC* getclassvardec(SCOPE* s, const char* name) { - CLASSVARDEC* curr = s->classvardecs; - while(curr != NULL) { - if(existstr(curr->base->names, name)) - return curr; - curr = curr->next; - } - if(s->previous != NULL) - return getclassvardec(s->previous, name); - return NULL; -} - SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) { - SUBROUTDEC* curr = s->subroutines; - while(curr != NULL) { - if(!strcmp(curr->name, name)) - return curr; - curr = curr->next; - } - if(s->previous != NULL) - return getsubroutdec(s->previous, name); - return NULL; + return (SUBROUTDEC*)(getbynamewithtype(s, name, subroutdec)->pointer); } CLASS* getclass(SCOPE* s, const char* name) { - 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; + return (CLASS*)(getbynamewithtype(s, name, class)->pointer); } SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) { @@ -201,7 +96,7 @@ SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) { notdeclared(call->parentname, call->debug); if(parent->type == class) - sd = getsubroutdecfromclass(parent->class, call->name); + sd = getsubroutdecfromclass(parent->pointer, call->name); else sd = getsubroutdecfromvar(s, parent, call); return sd; @@ -219,121 +114,88 @@ SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) { } // Generic getters -OBJ* getbyname(SCOPE* s, const char* name) { - OBJ* o = (OBJ*)malloc(sizeof(OBJ)); - - CLASSVARDEC* cvd = getclassvardec(s, name); - if(cvd != NULL) { - o->classvardec = cvd; - o->type = classvardec; - o->getdebug = getdebugvardec; - return o; - } - - VARDEC* vd = getvardec(s, name); - if(vd != NULL) { - o->vardec = vd; - o->type = vardec; - o->getdebug = getdebugsubroutdec; - return o; - } - - SUBROUTDEC* sd = getsubroutdec(s, name); - if(sd != NULL) { - o->subroutdec = sd; - o->type = subroutdec; - o->getdebug = getdebugclassvardec; - return o; - } - - CLASS* c = getclass(s, name); - if(c != NULL) { - o->class = c; - o->type = class; - o->getdebug = getdebugclass; - return o; - } - - free(o); - return NULL; -} - OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) { - while(names != NULL) { - OBJ* o = getbyname(s, names->content); - if(o != NULL) { - *retname = names->content; - return o; + OBJ* curr = s->objects; + 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; } - names = names->next; + curr = curr->next; } if(s->previous != NULL) return getbynamelist(s->previous, names, retname); 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 addclassvardec(SCOPE* s, CLASSVARDEC* v) { - ensurenoduplicates(s, v->base->names, v->base->debug); - CLASSVARDEC* new = copy(v, sizeof(CLASSVARDEC)); - new->next = s->classvardecs; - s->classvardecs = new; +void addobj(SCOPE* s, OBJ* o) { + ensurenoduplicate(s, o); + o->next = s->objects; + s->objects = o; } -void addvardec(SCOPE* s, VARDEC* v) { - ensurenoduplicates(s, v->names, v->debug); - VARDEC* new = copy(v, sizeof(VARDEC)); - new->next = s->vardecs; - s->vardecs = new; +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 addsubroutdec(SCOPE* s, SUBROUTDEC* sd) { - ensurenoduplicate(s, sd->name, sd->debug); - SUBROUTDEC* new = copy(sd, sizeof(SUBROUTDEC)); - new->next = s->subroutines; - s->subroutines = new; +void addany(SCOPE* s, void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) { + addobj(s, mkobj(pointer, type, debug, names)); } -void addclass(SCOPE* s, CLASS* c) { - ensurenoduplicate(s, c->name, c->debug); - CLASS* new = copy(c, sizeof(CLASS)); - new->next = s->classes; - s->classes = new; +void addclassvardecs(SCOPE* s, CLASSVARDEC* v) { + addany(s, v, classvardec, v->base->debug, v->base->names); + if(v->next != NULL) + addclassvardecs(s, v->next); } -// Group adding -void addclassvardecs(SCOPE* s, CLASSVARDEC* vs) { - CLASSVARDEC* next; - while(vs != NULL) { - next = vs->next; - addclassvardec(s, vs); - vs = next; - } +void addvardecs(SCOPE* s, VARDEC* v) { + addany(s, v, vardec, v->debug, v->names); + if(v->next != NULL) + addvardecs(s, v->next); } -void addvardecs(SCOPE* s, VARDEC* vs) { - VARDEC* next; - while(vs != NULL) { - next = vs->next; - addvardec(s, vs); - vs = next; - } -} - -void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss) { - SUBROUTDEC* next; - while(ss != NULL) { - next = ss->next; - addsubroutdec(s, ss); - ss = 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 addclasses(SCOPE* s, CLASS* c) { - CLASS* next; - while(c != NULL) { - next = c->next; - addclass(s, c); - c = next; - } + addany(s, c, class, c->debug, onestr(c->name)); + if(c->next != NULL) + addclasses(s, c->next); +} + +void addparameters(SCOPE* s, PARAMETER* p) { + addany(s, p, parameter, p->debug, onestr(p->name)); + if(p->next != NULL) + addparameters(s, p->next); } diff --git a/compiler/compiler-scopes.h b/compiler/compiler-scopes.h index d3d0a60..1c8e893 100644 --- a/compiler/compiler-scopes.h +++ b/compiler/compiler-scopes.h @@ -9,35 +9,30 @@ * certain semantic rules. */ // Data types -typedef struct scope { - SUBROUTDEC* subroutines; - CLASSVARDEC* classvardecs; - VARDEC* vardecs; - CLASS* classes; - int condlabelcount; - struct scope* previous; -} SCOPE; - typedef enum { - subroutdec, classvardec, vardec, class + subroutdec, classvardec, vardec, class, parameter } OBJTYPE; typedef struct object { + void* pointer; + DEBUGINFO* debug; + STRINGLIST* names; OBJTYPE type; - union { - SUBROUTDEC* subroutdec; - CLASSVARDEC* classvardec; - VARDEC* vardec; - CLASS* class; - }; - DEBUGINFO* (*getdebug)(struct object*); + struct object* next; } OBJ; +typedef struct scope { + OBJ* objects; + int condlabelcount; + 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); // Scope handling SCOPE* mkscope(SCOPE* prev); diff --git a/compiler/compiler.c b/compiler/compiler.c index c3777dd..9fd90e2 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -257,8 +257,10 @@ LINEBLOCK* compilestatements(SCOPE* s, CLASS* c, STATEMENT* sts) { } LINEBLOCK* compilefunbody(SCOPE* s, CLASS* c, SUBROUTBODY* b) { - // missing scope and vardecs handling - LINEBLOCK* head = compilestatements(s, c, b->statements); + SCOPE* myscope = mkscope(s); + if(b->vardecs != NULL) + addvardecs(s, b->vardecs); + LINEBLOCK* head = compilestatements(myscope, c, b->statements); return head; } @@ -291,8 +293,10 @@ LINEBLOCK* compilesubroutdec(SCOPE* s, CLASS* c, SUBROUTDEC* sd) { LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { SCOPE* topscope = mkscope(c->globalscope); - addclassvardecs(topscope, class->vardecs); - addsubroutdecs(topscope, class->subroutdecs); + if(class->vardecs != NULL) + addclassvardecs(topscope, class->vardecs); + if(class->subroutdecs != NULL) + addsubroutdecs(topscope, class->subroutdecs); LINEBLOCK* output = NULL; SUBROUTDEC* curr = class->subroutdecs; @@ -305,7 +309,7 @@ LINEBLOCK* compileclass(COMPILER* c, CLASS* class) { void compile(COMPILER* c) { LINEBLOCK* output = NULL; - CLASS* curr = c->globalscope->classes; + CLASS* curr = c->classes; while(curr != NULL) { output = mergelnblks(output, compileclass(c, curr)); curr = curr->next; @@ -317,5 +321,6 @@ COMPILER* mkcompiler(CLASS* classes) { COMPILER* c = (COMPILER*)malloc(sizeof(COMPILER)); c->globalscope = mkscope(NULL); addclasses(c->globalscope, classes); + c->classes = classes; return c; } diff --git a/compiler/compiler.h b/compiler/compiler.h index 6a09028..f9819e2 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -5,6 +5,7 @@ #include "vm-lines.h" typedef struct { + CLASS* classes; SCOPE* globalscope; LINEBLOCK* output; } COMPILER; diff --git a/parser/parser-structure.c b/parser/parser-structure.c index d1c0504..92f3cf6 100644 --- a/parser/parser-structure.c +++ b/parser/parser-structure.c @@ -87,11 +87,16 @@ 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* next; - while(next = parseclassvardec(p), next != NULL) { - curr->next = next; - curr= next; + CLASSVARDEC* nextc; + while(nextc = parseclassvardec(p), nextc != NULL) { + nextc->base->index = index; + index++; + curr->next = nextc; + curr = nextc; } if(curr != NULL) curr->next = NULL; @@ -136,10 +141,10 @@ SUBROUTDEC* parsesubroutdec(PARSER* p) { SUBROUTDEC* parsesubroutdecs(PARSER* p) { SUBROUTDEC* head = parsesubroutdec(p); SUBROUTDEC* curr = head; - SUBROUTDEC* next; - while(next = parsesubroutdec(p), next != NULL) { - curr->next = next; - curr = next; + SUBROUTDEC* nexts; + while(nexts = parsesubroutdec(p), nexts != NULL) { + curr->next = nexts; + curr = nexts; } if(curr != NULL) curr->next = NULL; @@ -150,6 +155,7 @@ PARAMETER* parseparameter(PARSER* p) { PARAMETER* param = (PARAMETER*)malloc(sizeof(PARAMETER)); if(equals(p, ")")) return NULL; + param->debug = getdebug(p); param->type = parsetype(p); param->name = parseidentifier(p); return param; @@ -157,10 +163,19 @@ 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, ",")) { next(p); - curr->next = parseparameter(p); + nextp = parseparameter(p); + if(nextp == NULL) + unexpected(p); + nextp->index = index; + curr->next = nextp; + index++; curr = curr->next; } if(curr != NULL) @@ -231,11 +246,16 @@ 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* next; - while(next = parsevardec(p), next != NULL) { - curr->next = next; - curr = next; + VARDEC* nextv; + while(nextv = parsevardec(p), nextv != NULL) { + nextv->index = index; + index++; + curr->next = nextv; + curr = nextv; } if(curr != NULL) curr->next = NULL; diff --git a/parser/parser-tree.h b/parser/parser-tree.h index 2525a14..0f758fd 100644 --- a/parser/parser-tree.h +++ b/parser/parser-tree.h @@ -60,6 +60,8 @@ typedef struct subroutdec { typedef struct parameter { char* type; char* name; + int index; + DEBUGINFO* debug; struct parameter* next; } PARAMETER; @@ -71,10 +73,11 @@ typedef struct subroutbody { typedef struct vardec { char* type; bool primitive; + int index; TOKENTYPE typeclass; STRINGLIST* names; - struct vardec* next; DEBUGINFO* debug; + struct vardec* next; } VARDEC; // Statements diff --git a/util.c b/util.c index 35a4f46..82b0ad5 100644 --- a/util.c +++ b/util.c @@ -40,6 +40,13 @@ char* itoa(int i) { return a; } +STRINGLIST* onestr(const char* str) { + STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST)); + strlist->content = ezheapstr(str); + strlist->next = NULL; + return strlist; +} + STRINGLIST* initstrlist(const char** strs, int count) { STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST)); STRINGLIST* curr = strlist; diff --git a/util.h b/util.h index e67847d..85e1f6d 100644 --- a/util.h +++ b/util.h @@ -28,6 +28,7 @@ int countplaces(int n); char* itoa(int i); void* copy(void* v, int size); +STRINGLIST* onestr(const char* str); STRINGLIST* initstrlist(const char** strs, int count); void printstrlist(STRINGLIST* strlist, FILE* stream); void freestrlist(STRINGLIST* strlist);