2020-12-21 13:05:49 -05:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "compiler-scopes.h"
|
|
|
|
|
|
|
|
// Error messages
|
2020-12-24 14:22:22 -05:00
|
|
|
void doubledeclaration(const char* name, OBJ* o1, OBJ* o2);
|
|
|
|
void ensurenoduplicate(SCOPE* s, OBJ* o);
|
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-24 14:22:22 -05:00
|
|
|
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type);
|
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);
|
|
|
|
|
|
|
|
// OBJ handling
|
|
|
|
|
|
|
|
VARDEC* tovardec(OBJ* obj) {
|
|
|
|
if (obj->type == classvardec)
|
2020-12-24 14:22:22 -05:00
|
|
|
return ((CLASSVARDEC*)(obj->pointer))->base;
|
2020-12-21 13:05:49 -05:00
|
|
|
else if (obj->type == vardec)
|
2020-12-24 14:22:22 -05:00
|
|
|
return (VARDEC*)(obj->pointer);
|
2020-12-21 13:05:49 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Error messages
|
2020-12-24 14:22:22 -05:00
|
|
|
void doubledeclaration(const char* name, OBJ* o1, OBJ* o2) {
|
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-24 14:22:22 -05:00
|
|
|
name, o1->debug->file, o1->debug->definedat, o2->debug->file, o2->debug->definedat);
|
2020-12-21 13:05:49 -05:00
|
|
|
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-24 14:22:22 -05:00
|
|
|
void ensurenoduplicate(SCOPE* s, OBJ* o) {
|
2020-12-21 19:50:55 -05:00
|
|
|
const char* othername;
|
2020-12-24 14:22:22 -05:00
|
|
|
OBJ* other = getbynamelist(s, o->names, &othername);
|
2020-12-21 13:05:49 -05:00
|
|
|
if(other != NULL)
|
2020-12-24 14:22:22 -05:00
|
|
|
doubledeclaration(othername, o, other);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Scope handling
|
|
|
|
|
|
|
|
SCOPE* mkscope(SCOPE* prev) {
|
|
|
|
SCOPE* s = (SCOPE*)malloc(sizeof(SCOPE));
|
2020-12-24 14:22:22 -05:00
|
|
|
s->objects = NULL;
|
2020-12-21 13:05:49 -05:00
|
|
|
s->previous = prev;
|
2020-12-22 13:45:12 -05:00
|
|
|
s->condlabelcount = 0;
|
2020-12-21 13:05:49 -05:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Single type getters
|
2020-12-21 19:50:55 -05:00
|
|
|
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
|
2020-12-24 14:22:22 -05:00
|
|
|
return (SUBROUTDEC*)(getbynamewithtype(s, name, subroutdec)->pointer);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-21 19:50:55 -05:00
|
|
|
CLASS* getclass(SCOPE* s, const char* name) {
|
2020-12-24 14:22:22 -05:00
|
|
|
return (CLASS*)(getbynamewithtype(s, name, class)->pointer);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
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-24 14:22:22 -05:00
|
|
|
sd = getsubroutdecfromclass(parent->pointer, 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* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) {
|
2020-12-24 14:22:22 -05:00
|
|
|
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;
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
2020-12-24 14:22:22 -05:00
|
|
|
curr = curr->next;
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
if(s->previous != NULL)
|
|
|
|
return getbynamelist(s->previous, names, retname);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
|
|
|
|
OBJ* getbyname(SCOPE* s, const char* name) {
|
|
|
|
STRINGLIST* onename = onestr(name);
|
|
|
|
const char* dummy;
|
|
|
|
return getbynamelist(s, onename, &dummy);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
OBJ* getbynamewithtype(SCOPE* s, const char* name, OBJTYPE type) {
|
|
|
|
OBJ* o = getbyname(s, name);
|
|
|
|
if(o->type != type)
|
|
|
|
notdeclared(name, o->debug);
|
|
|
|
return o;
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
// Scope adding
|
|
|
|
void addobj(SCOPE* s, OBJ* o) {
|
|
|
|
ensurenoduplicate(s, o);
|
|
|
|
o->next = s->objects;
|
|
|
|
s->objects = o;
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
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;
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
void addany(SCOPE* s, void* pointer, OBJTYPE type, DEBUGINFO* debug, STRINGLIST* names) {
|
|
|
|
addobj(s, mkobj(pointer, type, debug, names));
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
void addclassvardecs(SCOPE* s, CLASSVARDEC* v) {
|
|
|
|
addany(s, v, classvardec, v->base->debug, v->base->names);
|
|
|
|
if(v->next != NULL)
|
|
|
|
addclassvardecs(s, v->next);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 14:22:22 -05:00
|
|
|
void addvardecs(SCOPE* s, VARDEC* v) {
|
|
|
|
addany(s, v, vardec, v->debug, v->names);
|
|
|
|
if(v->next != NULL)
|
|
|
|
addvardecs(s, v->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
void addsubroutdecs(SCOPE* s, SUBROUTDEC* sd) {
|
|
|
|
addany(s, sd, subroutdec, sd->debug, onestr(sd->name));
|
|
|
|
if(sd->next != NULL)
|
|
|
|
addsubroutdecs(s, sd->next);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void addclasses(SCOPE* s, CLASS* c) {
|
2020-12-24 14:22:22 -05:00
|
|
|
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);
|
2020-12-21 13:05:49 -05:00
|
|
|
}
|