jack-compiler/compiler/compiler-scopes.c

340 lines
7.5 KiB
C
Raw Normal View History

2020-12-21 13:05:49 -05:00
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "compiler-scopes.h"
// INTERNAL FUNCTIONS
// Information gathering
2020-12-21 19:50:55 -05:00
bool existstr(STRINGLIST* strs, const char* str);
bool existclass(CLASS* c, const char* name);
2020-12-21 13:05:49 -05:00
DEBUGINFO* getdebuginfo(OBJ* obj);
// Error messages
2020-12-21 19:50:55 -05:00
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other);
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug);
2020-12-21 13:05:49 -05:00
// Scope handling
void popscope(SCOPE** s); // may be removed
// Single type getters
2020-12-21 19:50:55 -05:00
VARDEC* getvardec(SCOPE* s, const char* name);
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name);
2020-12-21 13:05:49 -05:00
// Generic getters
2020-12-21 19:50:55 -05:00
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname);
2020-12-21 13:05:49 -05:00
// Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
void addvardec(SCOPE* s, VARDEC* v);
2020-12-21 18:35:41 -05:00
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd);
2020-12-21 13:05:49 -05:00
void addclass(SCOPE* s, CLASS* c);
// DEFINITIONS
// Information gathering
2020-12-21 19:50:55 -05:00
bool existstr(STRINGLIST* strs, const char* str) {
2020-12-21 13:05:49 -05:00
while(strs != NULL) {
if(!strcmp(strs->content, str))
return true;
strs = strs->next;
}
return false;
}
2020-12-21 19:50:55 -05:00
bool existclass(CLASS* c, const char* name) {
2020-12-21 13:05:49 -05:00
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;
}
2020-12-21 18:35:41 -05:00
DEBUGINFO* getdebugsubroutdec(OBJ* obj) {
return obj->subroutdec->debug;
2020-12-21 13:05:49 -05:00
}
DEBUGINFO* getdebugclass(OBJ* obj) {
return obj->class->debug;
}
VARDEC* tovardec(OBJ* obj) {
if (obj->type == classvardec)
return obj->classvardec->base;
else if (obj->type == vardec)
return obj->vardec;
return NULL;
}
// Error messages
2020-12-21 19:50:55 -05:00
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other) {
2020-12-21 13:05:49 -05:00
DEBUGINFO* debugother = other->getdebug(other);
2020-12-21 16:11:23 -05:00
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
2020-12-21 13:05:49 -05:00
name, debug->file, debug->definedat, debugother->file, debugother->definedat);
exit(1);
}
2020-12-21 19:50:55 -05:00
void notdeclared(const char* name, DEBUGINFO* debug) {
2020-12-21 16:11:23 -05:00
eprintf("'%s' not declared; file '%s', line %i\n", name, debug->file, debug->definedat);
2020-12-21 13:05:49 -05:00
exit(1);
}
void invalidparent(SUBROUTCALL* call) {
2020-12-21 16:11:23 -05:00
eprintf("Invalid subroutine parent '%s'; file '%s', line %i\n", call->parentname, call->debug->file, call->debug->definedat);
2020-12-21 13:05:49 -05:00
exit(1);
}
2020-12-21 19:50:55 -05:00
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug) {
2020-12-21 13:05:49 -05:00
OBJ* other = getbyname(s, name);
if(other != NULL)
doubledeclaration(name, debug, other);
}
void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) {
2020-12-21 19:50:55 -05:00
const char* othername;
2020-12-21 13:05:49 -05:00
OBJ* other = getbynamelist(s, names, &othername);
if(other != NULL)
doubledeclaration(othername, debug, 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->previous = prev;
2020-12-22 13:45:12 -05:00
s->condlabelcount = 0;
2020-12-21 13:05:49 -05:00
return s;
}
void popscope(SCOPE** s) { // might be useless
SCOPE* prev = (*s)->previous;
free(*s);
(*s) = prev;
}
// Single type getters
2020-12-21 19:50:55 -05:00
VARDEC* getvardec(SCOPE* s, const char* name) {
2020-12-21 13:05:49 -05:00
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;
}
2020-12-21 19:50:55 -05:00
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name) {
2020-12-21 13:05:49 -05:00
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;
}
2020-12-21 19:50:55 -05:00
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
2020-12-21 18:35:41 -05:00
SUBROUTDEC* curr = s->subroutines;
2020-12-21 13:05:49 -05:00
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
if(s->previous != NULL)
2020-12-21 18:35:41 -05:00
return getsubroutdec(s->previous, name);
2020-12-21 13:05:49 -05:00
return NULL;
}
2020-12-21 19:50:55 -05:00
CLASS* getclass(SCOPE* s, const char* name) {
2020-12-21 13:05:49 -05:00
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;
}
2020-12-21 19:50:55 -05:00
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) {
2020-12-21 18:35:41 -05:00
SUBROUTDEC* curr = c->subroutdecs;
2020-12-21 13:05:49 -05:00
while(curr != NULL) {
if(!strcmp(curr->name, name))
return curr;
curr = curr->next;
}
return NULL;
}
2020-12-21 18:35:41 -05:00
SUBROUTDEC* getsubroutdecfromvar(SCOPE* s, OBJ* var, SUBROUTCALL* call) {
2020-12-21 13:05:49 -05:00
VARDEC* vd = tovardec(var);
if(vd == NULL || vd->primitive)
invalidparent(call);
CLASS* c = getclass(s, vd->type);
2020-12-21 18:35:41 -05:00
return getsubroutdecfromclass(c, call->name);
2020-12-21 13:05:49 -05:00
}
2020-12-21 18:35:41 -05:00
SUBROUTDEC* getsubroutdecfromparent(SCOPE* s, SUBROUTCALL* call) {
SUBROUTDEC* sd;
2020-12-21 13:05:49 -05:00
OBJ* parent = getbyname(s, call->parentname);
if(parent == NULL)
notdeclared(call->parentname, call->debug);
if(parent->type == class)
2020-12-21 18:35:41 -05:00
sd = getsubroutdecfromclass(parent->class, call->name);
2020-12-21 13:05:49 -05:00
else
2020-12-21 18:35:41 -05:00
sd = getsubroutdecfromvar(s, parent, call);
2020-12-21 13:05:49 -05:00
return sd;
}
2020-12-21 18:35:41 -05:00
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
SUBROUTDEC* sd;
2020-12-21 13:05:49 -05:00
if(call->parentname != NULL)
2020-12-21 18:35:41 -05:00
sd = getsubroutdecfromparent(s, call);
2020-12-21 13:05:49 -05:00
else
2020-12-21 18:35:41 -05:00
sd = getsubroutdec(s, call->name);
2020-12-21 13:05:49 -05:00
if(sd == NULL)
notdeclared(call->name, call->debug);
return sd;
}
// Generic getters
2020-12-21 19:50:55 -05:00
OBJ* getbyname(SCOPE* s, const char* name) {
2020-12-21 13:05:49 -05:00
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;
2020-12-21 18:35:41 -05:00
o->getdebug = getdebugsubroutdec;
2020-12-21 13:05:49 -05:00
return o;
}
2020-12-21 18:35:41 -05:00
SUBROUTDEC* sd = getsubroutdec(s, name);
2020-12-21 13:05:49 -05:00
if(sd != NULL) {
2020-12-21 18:35:41 -05:00
o->subroutdec = sd;
o->type = subroutdec;
2020-12-21 13:05:49 -05:00
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;
}
2020-12-21 19:50:55 -05:00
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) {
2020-12-21 13:05:49 -05:00
while(names != NULL) {
OBJ* o = getbyname(s, names->content);
if(o != NULL) {
*retname = names->content;
return o;
}
names = names->next;
}
if(s->previous != NULL)
return getbynamelist(s->previous, names, retname);
return NULL;
}
// Scope adding
void addclassvardec(SCOPE* s, CLASSVARDEC* v) {
ensurenoduplicates(s, v->base->names, v->base->debug);
2020-12-21 14:49:37 -05:00
CLASSVARDEC* new = copy(v, sizeof(CLASSVARDEC));
new->next = s->classvardecs;
s->classvardecs = new;
2020-12-21 13:05:49 -05:00
}
void addvardec(SCOPE* s, VARDEC* v) {
ensurenoduplicates(s, v->names, v->debug);
2020-12-21 14:49:37 -05:00
VARDEC* new = copy(v, sizeof(VARDEC));
new->next = s->vardecs;
s->vardecs = new;
2020-12-21 13:05:49 -05:00
}
2020-12-21 18:35:41 -05:00
void addsubroutdec(SCOPE* s, SUBROUTDEC* sd) {
2020-12-21 13:05:49 -05:00
ensurenoduplicate(s, sd->name, sd->debug);
2020-12-21 18:35:41 -05:00
SUBROUTDEC* new = copy(sd, sizeof(SUBROUTDEC));
2020-12-21 14:49:37 -05:00
new->next = s->subroutines;
s->subroutines = new;
2020-12-21 13:05:49 -05:00
}
void addclass(SCOPE* s, CLASS* c) {
ensurenoduplicate(s, c->name, c->debug);
2020-12-21 14:49:37 -05:00
CLASS* new = copy(c, sizeof(CLASS));
new->next = s->classes;
s->classes = new;
2020-12-21 13:05:49 -05:00
}
// Group adding
void addclassvardecs(SCOPE* s, CLASSVARDEC* vs) {
2020-12-21 14:49:37 -05:00
CLASSVARDEC* next;
2020-12-21 13:05:49 -05:00
while(vs != NULL) {
2020-12-21 14:49:37 -05:00
next = vs->next;
2020-12-21 13:05:49 -05:00
addclassvardec(s, vs);
2020-12-21 14:49:37 -05:00
vs = next;
2020-12-21 13:05:49 -05:00
}
}
void addvardecs(SCOPE* s, VARDEC* vs) {
2020-12-21 14:49:37 -05:00
VARDEC* next;
2020-12-21 13:05:49 -05:00
while(vs != NULL) {
2020-12-21 14:49:37 -05:00
next = vs->next;
2020-12-21 13:05:49 -05:00
addvardec(s, vs);
2020-12-21 14:49:37 -05:00
vs = next;
2020-12-21 13:05:49 -05:00
}
}
2020-12-21 18:35:41 -05:00
void addsubroutdecs(SCOPE* s, SUBROUTDEC* ss) {
SUBROUTDEC* next;
2020-12-21 13:05:49 -05:00
while(ss != NULL) {
2020-12-21 14:49:37 -05:00
next = ss->next;
2020-12-21 18:35:41 -05:00
addsubroutdec(s, ss);
2020-12-21 14:49:37 -05:00
ss = next;
2020-12-21 13:05:49 -05:00
}
}
void addclasses(SCOPE* s, CLASS* c) {
2020-12-21 14:49:37 -05:00
CLASS* next;
2020-12-21 13:05:49 -05:00
while(c != NULL) {
2020-12-21 14:49:37 -05:00
next = c->next;
2020-12-21 13:05:49 -05:00
addclass(s, c);
2020-12-21 14:49:37 -05:00
c = next;
2020-12-21 13:05:49 -05:00
}
}