|
@@ -15,6 +15,11 @@
|
|
|
#define RETURN_BUFFER 16
|
|
|
#define BREAK_BUFFER 32
|
|
|
|
|
|
+#define DT_OPERATION(op) \
|
|
|
+ case DT_INT: cAddOperation(OP_##op##_INT); break; \
|
|
|
+ case DT_BOOL: cAddOperation(OP_##op##_BOOL); break; \
|
|
|
+ case DT_FLOAT: cAddOperation(OP_##op##_FLOAT); break;
|
|
|
+
|
|
|
static jmp_buf errorJump;
|
|
|
static char error[ERROR_LENGTH] = {'\0'};
|
|
|
|
|
@@ -209,31 +214,39 @@ static DataType cCallFunction(const char* name) {
|
|
|
}
|
|
|
|
|
|
static void cWalkStruct(Variable* v) {
|
|
|
- int pointers;
|
|
|
- if(cConsumeTokenIf(T_ARROW)) {
|
|
|
- pointers = 1;
|
|
|
- cAddOperation(OP_REFERENCE);
|
|
|
- } else if(cConsumeTokenIf(T_POINT)) {
|
|
|
- pointers = 0;
|
|
|
- } else {
|
|
|
- return;
|
|
|
- }
|
|
|
- Struct* st = dtGetStruct(&structs, v->type);
|
|
|
- if(st == NULL || v->type.pointers != pointers) {
|
|
|
- DataType w = v->type;
|
|
|
- w.pointers = pointers;
|
|
|
- cError("%s is not %s but %s", v->name, cGetName(w), cGetName(v->type));
|
|
|
+ int offset = 0;
|
|
|
+ while(true) {
|
|
|
+ int pointers;
|
|
|
+ if(cConsumeTokenIf(T_ARROW)) {
|
|
|
+ pointers = 1;
|
|
|
+ cAddOperation(OP_REFERENCE);
|
|
|
+ } else if(cConsumeTokenIf(T_POINT)) {
|
|
|
+ pointers = 0;
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ Struct* st = dtGetStruct(&structs, v->type);
|
|
|
+ if(st == NULL || v->type.pointers != pointers) {
|
|
|
+ DataType w = v->type;
|
|
|
+ w.pointers = pointers;
|
|
|
+ cError("%s is not %s but %s", v->name, cGetName(w),
|
|
|
+ cGetName(v->type));
|
|
|
+ }
|
|
|
+ cConsumeToken(T_LITERAL);
|
|
|
+ const char* name = cReadString();
|
|
|
+ Variable inner;
|
|
|
+ if(vSearchStruct(&inner, &structs, st, name)) {
|
|
|
+ cError("%s has no member %s", v->name, name);
|
|
|
+ }
|
|
|
+ v->type = inner.type;
|
|
|
+ v->name = inner.name;
|
|
|
+ offset += inner.address;
|
|
|
}
|
|
|
- cConsumeToken(T_LITERAL);
|
|
|
- const char* name = cReadString();
|
|
|
- Variable inner;
|
|
|
- if(vSearchStruct(&inner, &structs, st, name)) {
|
|
|
- cError("%s has no member %s", v->name, name);
|
|
|
+ if(offset > 0) {
|
|
|
+ cAddOperation(OP_PUSH_INT);
|
|
|
+ cAddInt(offset);
|
|
|
+ cAddOperation(OP_ADD_INT);
|
|
|
}
|
|
|
- v->type = inner.type;
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(inner.address);
|
|
|
- cAddOperation(OP_ADD_INT);
|
|
|
}
|
|
|
|
|
|
static void cReference(Variable* v, int dimension) {
|
|
@@ -251,10 +264,12 @@ static void cReference(Variable* v, int dimension) {
|
|
|
}
|
|
|
|
|
|
static void cLoadRef(Variable* v) {
|
|
|
- switch(dtAsInt(v->type)) {
|
|
|
- case DT_INT: cAddOperation(OP_LOAD_INT); break;
|
|
|
- case DT_BOOL: cAddOperation(OP_LOAD_BOOL); break;
|
|
|
- case DT_FLOAT: cAddOperation(OP_LOAD_FLOAT); break;
|
|
|
+ if(dtIsPointer(v->type)) {
|
|
|
+ cAddOperation(OP_LOAD_INT);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch(v->type.type) {
|
|
|
+ DT_OPERATION(LOAD);
|
|
|
case DT_STRUCT:
|
|
|
{
|
|
|
Struct* st = dtGetStruct(&structs, v->type);
|
|
@@ -265,12 +280,7 @@ static void cLoadRef(Variable* v) {
|
|
|
cAddInt(dtGetSize(v->type, &structs));
|
|
|
break;
|
|
|
}
|
|
|
- default:
|
|
|
- if(dtIsPointer(v->type)) {
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
- } else {
|
|
|
- cError("cannot load type %s", cGetName(v->type));
|
|
|
- }
|
|
|
+ default: cError("cannot load type %s", cGetName(v->type));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -278,16 +288,13 @@ static void cStore(Variable* v, DataType dt, const char* name) {
|
|
|
if(!dtCompare(v->type, dt)) {
|
|
|
cInvalidOperation(v->type, dt, name);
|
|
|
}
|
|
|
- switch(dtAsInt(v->type)) {
|
|
|
- case DT_INT: cAddOperation(OP_STORE_INT); break;
|
|
|
- case DT_BOOL: cAddOperation(OP_STORE_BOOL); break;
|
|
|
- case DT_FLOAT: cAddOperation(OP_STORE_FLOAT); break;
|
|
|
- default:
|
|
|
- if(dtIsPointer(v->type)) {
|
|
|
- cAddOperation(OP_STORE_ARRAY);
|
|
|
- } else {
|
|
|
- cError("cannot store type %s", cGetName(v->type));
|
|
|
- }
|
|
|
+ if(dtIsPointer(v->type)) {
|
|
|
+ cAddOperation(OP_STORE_ARRAY);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch(v->type.type) {
|
|
|
+ DT_OPERATION(STORE);
|
|
|
+ default: cError("cannot store type %s", cGetName(v->type));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -385,10 +392,12 @@ static DataType cPreChange(int change, const char* name) {
|
|
|
static DataType cPreUnary() {
|
|
|
if(cConsumeTokenIf(T_SUB)) {
|
|
|
DataType result = cPrimary();
|
|
|
- switch(dtAsInt(result)) {
|
|
|
- case DT_INT: cAddOperation(OP_INVERT_SIGN_INT); break;
|
|
|
- case DT_FLOAT: cAddOperation(OP_INVERT_SIGN_FLOAT); break;
|
|
|
- default: cError("cannot invert sign of %s", cGetName(result));
|
|
|
+ if(dtCompare(result, dtInt())) {
|
|
|
+ cAddOperation(OP_INVERT_SIGN_INT);
|
|
|
+ } else if(dtCompare(result, dtFloat())) {
|
|
|
+ cAddOperation(OP_INVERT_SIGN_FLOAT);
|
|
|
+ } else {
|
|
|
+ cError("cannot invert sign of %s", cGetName(result));
|
|
|
}
|
|
|
return result;
|
|
|
} else if(cConsumeTokenIf(T_INCREMENT)) {
|
|
@@ -729,21 +738,27 @@ static void cReturn() {
|
|
|
if(!dtCompare(dt, returnType)) {
|
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
|
}
|
|
|
- switch(dtAsInt(dt)) {
|
|
|
- case DT_INT: cAddReturn(OP_RETURN_INT); break;
|
|
|
- case DT_BOOL: cAddReturn(OP_RETURN_BOOL); break;
|
|
|
- case DT_FLOAT: cAddReturn(OP_RETURN_FLOAT); break;
|
|
|
- default: cError("cannot return %s", cGetName(dt));
|
|
|
+ if(dtCompare(dt, dtInt())) {
|
|
|
+ cAddReturn(OP_RETURN_INT);
|
|
|
+ } else if(dtCompare(dt, dtBool())) {
|
|
|
+ cAddReturn(OP_RETURN_BOOL);
|
|
|
+ } else if(dtCompare(dt, dtFloat())) {
|
|
|
+ cAddReturn(OP_RETURN_FLOAT);
|
|
|
+ } else {
|
|
|
+ cError("cannot return %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
}
|
|
|
|
|
|
static void cPrint() {
|
|
|
DataType dt = cExpression();
|
|
|
- switch(dtAsInt(dt)) {
|
|
|
- case DT_INT: cAddOperation(OP_PRINT_INT); break;
|
|
|
- case DT_FLOAT: cAddOperation(OP_PRINT_FLOAT); break;
|
|
|
- case DT_BOOL: cAddOperation(OP_PRINT_BOOL); break;
|
|
|
+ if(dtIsPointer(dt)) {
|
|
|
+ cAddOperation(OP_PRINT_INT);
|
|
|
+ cConsumeToken(T_SEMICOLON);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch(dt.type) {
|
|
|
+ DT_OPERATION(PRINT);
|
|
|
default: cError("cannot print type %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
@@ -1065,6 +1080,7 @@ static void cStruct() {
|
|
|
cError("struct registered twice");
|
|
|
}
|
|
|
Struct* st = stsAdd(&structs, name);
|
|
|
+ DataType self = dtStruct(st);
|
|
|
cConsumeToken(T_OPEN_CURVED_BRACKET);
|
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
|
Token t = cReadTokenAndLine();
|
|
@@ -1073,9 +1089,22 @@ static void cStruct() {
|
|
|
case T_INT: dt = dtInt(); break;
|
|
|
case T_BOOL: dt = dtBool(); break;
|
|
|
case T_FLOAT: dt = dtFloat(); break;
|
|
|
+ case T_LITERAL:
|
|
|
+ {
|
|
|
+ const char* name = cReadString();
|
|
|
+ Struct* st = stsSearch(&structs, name);
|
|
|
+ if(st == NULL) {
|
|
|
+ cError("struct %s does not exist");
|
|
|
+ }
|
|
|
+ dt = dtStruct(st);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
|
dt = cExtendType(dt);
|
|
|
+ if(dtCompare(dt, self)) {
|
|
|
+ cError("struct %s contains itself", name);
|
|
|
+ }
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
|
stAddVariable(st, name, dt);
|