|
@@ -208,47 +208,89 @@ static DataType cCallFunction(const char* name) {
|
|
|
return found->returnType;
|
|
|
}
|
|
|
|
|
|
-static DataType cLoadRef(Variable* v, Operation op, DataType dt) {
|
|
|
+static void cAddOffset(int offset) {
|
|
|
+ if(offset > 0) {
|
|
|
+ cAddOperation(OP_PUSH_INT);
|
|
|
+ cAddInt(offset);
|
|
|
+ cAddOperation(OP_ADD_INT);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static DataType cLoadRef(Variable* v, Operation op, DataType dt, int offset) {
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
|
cAddInt(v->address);
|
|
|
+ cAddOffset(offset);
|
|
|
cAddOperation(op);
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
-static DataType cLoadVariable(Variable* v) {
|
|
|
- if(dtCompare(v->type, dtToReference(dtInt()))) {
|
|
|
- return cLoadRef(v, OP_REF_LOAD_INT, dtInt());
|
|
|
- } else if(dtCompare(v->type, dtToReference(dtFloat()))) {
|
|
|
- return cLoadRef(v, OP_REF_LOAD_FLOAT, dtFloat());
|
|
|
- } else if(dtCompare(v->type, dtToReference(dtBool()))) {
|
|
|
- return cLoadRef(v, OP_REF_LOAD_BOOL, dtBool());
|
|
|
+static DataType cAddVariable(Operation op, Variable* v) {
|
|
|
+ cAddOperation(op);
|
|
|
+ cAddInt(v->address);
|
|
|
+ return v->type;
|
|
|
+}
|
|
|
+
|
|
|
+static DataType cLoadVariable(Variable* v, Variable* sv) {
|
|
|
+ DataType type = v->type;
|
|
|
+ int offset = 0;
|
|
|
+ if(dtIsStruct(type) && sv->type.type != DT_VOID) {
|
|
|
+ sv->address += v->address;
|
|
|
+ return cLoadVariable(sv, sv);
|
|
|
+ } else if(dtIsStructRef(type)) {
|
|
|
+ type = dtToReference(sv->type);
|
|
|
+ offset = sv->address;
|
|
|
+ }
|
|
|
+ if(dtCompare(type, dtToReference(dtInt()))) {
|
|
|
+ return cLoadRef(v, OP_REF_LOAD_INT, dtInt(), offset);
|
|
|
+ } else if(dtCompare(type, dtToReference(dtFloat()))) {
|
|
|
+ return cLoadRef(v, OP_REF_LOAD_FLOAT, dtFloat(), offset);
|
|
|
+ } else if(dtCompare(type, dtToReference(dtBool()))) {
|
|
|
+ return cLoadRef(v, OP_REF_LOAD_BOOL, dtBool(), offset);
|
|
|
}
|
|
|
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;
|
|
|
- default: cError("cannot load type %s", cGetName(v->type));
|
|
|
+ case DT_INT: return cAddVariable(OP_LOAD_INT, v);
|
|
|
+ case DT_BOOL: return cAddVariable(OP_LOAD_BOOL, v);
|
|
|
+ case DT_FLOAT: return cAddVariable(OP_LOAD_FLOAT, v);
|
|
|
+ case DT_STRUCT:
|
|
|
+ {
|
|
|
+ Struct* st = dtGetStruct(&structs, v->type);
|
|
|
+ if(st == NULL) {
|
|
|
+ cError("compiler struct error");
|
|
|
+ }
|
|
|
+ int address = v->address;
|
|
|
+ for(int i = 0; i < st->amount; i++) {
|
|
|
+ Variable v = {st->vars[i].name, st->vars[i].type, address};
|
|
|
+ cLoadVariable(&v, sv);
|
|
|
+ address += dtGetSize(v.type, &structs);
|
|
|
+ }
|
|
|
+ return v->type;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ cError("cannot load type %s", cGetName(v->type));
|
|
|
+ return dtVoid();
|
|
|
}
|
|
|
- cAddInt(v->address);
|
|
|
- return v->type;
|
|
|
}
|
|
|
|
|
|
-static bool cStoreRef(Variable* v, DataType should, DataType dt, Operation op) {
|
|
|
- if(dtCompare(v->type, dtToReference(should)) && dtCompare(dt, should)) {
|
|
|
+static bool cStoreRef(Variable* v, Variable* sv, DataType should, DataType dt,
|
|
|
+ Operation op) {
|
|
|
+ DataType type = v->type;
|
|
|
+ int offset = 0;
|
|
|
+ if(dtIsStructRef(type)) {
|
|
|
+ type = dtToReference(sv->type);
|
|
|
+ offset = sv->address;
|
|
|
+ }
|
|
|
+ if(dtCompare(type, dtToReference(should)) && dtCompare(dt, should)) {
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
|
cAddInt(v->address);
|
|
|
+ cAddOffset(offset);
|
|
|
cAddOperation(op);
|
|
|
return true;
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static void cStoreVariable(Variable* v, DataType dt, const char* name) {
|
|
|
- if(cStoreRef(v, dtInt(), dt, OP_REF_STORE_INT) ||
|
|
|
- cStoreRef(v, dtFloat(), dt, OP_REF_STORE_FLOAT) ||
|
|
|
- cStoreRef(v, dtBool(), dt, OP_REF_STORE_BOOL)) {
|
|
|
- return;
|
|
|
- } else if(!dtCompare(v->type, dt)) {
|
|
|
+static void cStore(Variable* v, DataType dt, const char* name) {
|
|
|
+ if(!dtCompare(v->type, dt)) {
|
|
|
cInvalidOperation(v->type, dt, name);
|
|
|
} else if(v->type.reference) {
|
|
|
cAddOperation(OP_STORE_INT);
|
|
@@ -269,6 +311,21 @@ static void cStoreVariable(Variable* v, DataType dt, const char* name) {
|
|
|
cAddInt(v->address);
|
|
|
}
|
|
|
|
|
|
+static void cStoreVariable(Variable* v, Variable* sv, DataType dt,
|
|
|
+ const char* name) {
|
|
|
+ if(cStoreRef(v, sv, dtInt(), dt, OP_REF_STORE_INT) ||
|
|
|
+ cStoreRef(v, sv, dtFloat(), dt, OP_REF_STORE_FLOAT) ||
|
|
|
+ cStoreRef(v, sv, dtBool(), dt, OP_REF_STORE_BOOL)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(dtIsStruct(v->type) && sv->type.type != DT_VOID) {
|
|
|
+ sv->address += v->address;
|
|
|
+ cStore(sv, dt, name);
|
|
|
+ } else {
|
|
|
+ cStore(v, dt, name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
@@ -285,6 +342,24 @@ static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
return dtInt();
|
|
|
}
|
|
|
|
|
|
+static void cWalkStruct(Variable* v, Variable* sv) {
|
|
|
+ sv->address = 0;
|
|
|
+ sv->name = "";
|
|
|
+ sv->type = dtVoid();
|
|
|
+ if(!cConsumeTokenIf(T_POINT)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Struct* st = dtGetStruct(&structs, v->type);
|
|
|
+ if(st == NULL) {
|
|
|
+ cError("%s is not a struct but %s", v->name, cGetName(v->type));
|
|
|
+ }
|
|
|
+ cConsumeToken(T_LITERAL);
|
|
|
+ const char* name = cReadString();
|
|
|
+ if(vSearchStruct(sv, &structs, st, name)) {
|
|
|
+ cError("%s has no member %s", v->name, name);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static DataType cLiteral() {
|
|
|
const char* literal = cReadString();
|
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
@@ -298,12 +373,14 @@ static DataType cLiteral() {
|
|
|
if(v == NULL) {
|
|
|
cNotDeclared(literal);
|
|
|
}
|
|
|
+ Variable sv;
|
|
|
+ cWalkStruct(v, &sv);
|
|
|
if(cConsumeTokenIf(T_INCREMENT)) {
|
|
|
return cPostChange(v, 1, "++");
|
|
|
} else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
|
return cPostChange(v, -1, "--");
|
|
|
}
|
|
|
- return cLoadVariable(v);
|
|
|
+ return cLoadVariable(v, &sv);
|
|
|
}
|
|
|
|
|
|
static DataType cBracketPrimary() {
|
|
@@ -400,8 +477,13 @@ static DataType cPreUnary() {
|
|
|
if(v == NULL) {
|
|
|
cNotDeclared(literal);
|
|
|
}
|
|
|
- cAddOperation(OP_VAR_REF);
|
|
|
- cAddInt(v->address);
|
|
|
+ if(v->type.reference) {
|
|
|
+ cAddOperation(OP_LOAD_INT);
|
|
|
+ cAddInt(v->address);
|
|
|
+ } else {
|
|
|
+ cAddOperation(OP_VAR_REF);
|
|
|
+ cAddInt(v->address);
|
|
|
+ }
|
|
|
return dtToReference(v->type);
|
|
|
}
|
|
|
return cPrimary();
|
|
@@ -568,11 +650,11 @@ static DataType cExpression() {
|
|
|
return cOr();
|
|
|
}
|
|
|
|
|
|
-static void cOperationSet(Variable* v, const TypedOp* op) {
|
|
|
- DataType a = cLoadVariable(v);
|
|
|
+static void cOperationSet(Variable* v, Variable* sv, const TypedOp* op) {
|
|
|
+ DataType a = cLoadVariable(v, sv);
|
|
|
DataType b = cExpression();
|
|
|
cAddTypeOperation(a, b, op);
|
|
|
- cStoreVariable(v, b, "=");
|
|
|
+ cStoreVariable(v, sv, b, "=");
|
|
|
}
|
|
|
|
|
|
static void cAddPostLineChange(Variable* v, int change, const char* name) {
|
|
@@ -596,16 +678,6 @@ static void cDeclareStruct(Struct* st) {
|
|
|
cDeclared(var);
|
|
|
}
|
|
|
vAdd(&vars, var, dtStruct(st), &structs);
|
|
|
- int varLength = strlen(var);
|
|
|
- for(int i = 0; i < st->amount; i++) {
|
|
|
- int length = strlen(st->vars[i].name);
|
|
|
- char* fullName = malloc(varLength + length + 2);
|
|
|
- memcpy(fullName, var, varLength);
|
|
|
- fullName[varLength] = '.';
|
|
|
- memcpy(fullName + varLength + 1, st->vars[i].name, length + 1);
|
|
|
- vAdd(&vars, fullName, st->vars[i].type, &structs);
|
|
|
- free(fullName);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
static void cLineLiteral() {
|
|
@@ -626,19 +698,24 @@ static void cLineLiteral() {
|
|
|
if(v == NULL) {
|
|
|
cNotDeclared(literal);
|
|
|
}
|
|
|
+ Variable sv;
|
|
|
+ sv.type = dtVoid();
|
|
|
+ cWalkStruct(v, &sv);
|
|
|
Token t = cReadTokenAndLine();
|
|
|
switch(t) {
|
|
|
- case T_SET: cStoreVariable(v, cExpression(), "="); break;
|
|
|
- case T_ADD_SET: cOperationSet(v, &TYPED_ADD); break;
|
|
|
- case T_SUB_SET: cOperationSet(v, &TYPED_SUB); break;
|
|
|
- case T_MUL_SET: cOperationSet(v, &TYPED_MUL); break;
|
|
|
- case T_DIV_SET: cOperationSet(v, &TYPED_DIV); break;
|
|
|
- case T_MOD_SET: cOperationSet(v, &TYPED_MOD); break;
|
|
|
- case T_BIT_AND_SET: cOperationSet(v, &TYPED_BIT_AND); break;
|
|
|
- case T_BIT_OR_SET: cOperationSet(v, &TYPED_BIT_OR); break;
|
|
|
- case T_BIT_XOR_SET: cOperationSet(v, &TYPED_BIT_XOR); break;
|
|
|
- case T_LEFT_SHIFT_SET: cOperationSet(v, &TYPED_LEFT_SHIFT); break;
|
|
|
- case T_RIGHT_SHIFT_SET: cOperationSet(v, &TYPED_RIGHT_SHIFT); break;
|
|
|
+ case T_SET: cStoreVariable(v, &sv, cExpression(), "="); break;
|
|
|
+ case T_ADD_SET: cOperationSet(v, &sv, &TYPED_ADD); break;
|
|
|
+ case T_SUB_SET: cOperationSet(v, &sv, &TYPED_SUB); break;
|
|
|
+ case T_MUL_SET: cOperationSet(v, &sv, &TYPED_MUL); break;
|
|
|
+ case T_DIV_SET: cOperationSet(v, &sv, &TYPED_DIV); break;
|
|
|
+ case T_MOD_SET: cOperationSet(v, &sv, &TYPED_MOD); break;
|
|
|
+ case T_BIT_AND_SET: cOperationSet(v, &sv, &TYPED_BIT_AND); break;
|
|
|
+ case T_BIT_OR_SET: cOperationSet(v, &sv, &TYPED_BIT_OR); break;
|
|
|
+ case T_BIT_XOR_SET: cOperationSet(v, &sv, &TYPED_BIT_XOR); break;
|
|
|
+ case T_LEFT_SHIFT_SET: cOperationSet(v, &sv, &TYPED_LEFT_SHIFT); break;
|
|
|
+ case T_RIGHT_SHIFT_SET:
|
|
|
+ cOperationSet(v, &sv, &TYPED_RIGHT_SHIFT);
|
|
|
+ break;
|
|
|
case T_INCREMENT: cAddPostLineChange(v, 1, "++"); break;
|
|
|
case T_DECREMENT: cAddPostLineChange(v, -1, "--"); break;
|
|
|
default: cUnexpectedToken(t);
|
|
@@ -787,7 +864,7 @@ static void cDeclare(DataType dt) {
|
|
|
}
|
|
|
v = vAdd(&vars, var, dt, &structs);
|
|
|
cConsumeToken(T_SET);
|
|
|
- cStoreVariable(v, cExpression(), "=");
|
|
|
+ cStore(v, cExpression(), "=");
|
|
|
}
|
|
|
|
|
|
static void cAddPreLineChange(int change, const char* name) {
|
|
@@ -899,9 +976,7 @@ static void cFunctionCommaOrEnd(Function* f) {
|
|
|
}
|
|
|
|
|
|
static void cFunctionAddArgument(Function* f, DataType dt) {
|
|
|
- if(cConsumeTokenIf(T_BIT_AND)) {
|
|
|
- dt = dtToReference(dt);
|
|
|
- }
|
|
|
+ dt = cExtendType(dt);
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
|
Variable* v = vSearchScope(&vars, name);
|
|
@@ -921,6 +996,16 @@ static void cFunctionArgument(Function* f) {
|
|
|
case T_INT: cFunctionAddArgument(f, dtInt()); break;
|
|
|
case T_FLOAT: cFunctionAddArgument(f, dtFloat()); break;
|
|
|
case T_BOOL: cFunctionAddArgument(f, dtBool()); break;
|
|
|
+ case T_LITERAL:
|
|
|
+ {
|
|
|
+ const char* structName = cReadString();
|
|
|
+ Struct* st = stsSearch(&structs, structName);
|
|
|
+ if(st == NULL) {
|
|
|
+ cError("struct %s does not exist");
|
|
|
+ }
|
|
|
+ cFunctionAddArgument(f, dtStruct(st));
|
|
|
+ break;
|
|
|
+ }
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
|
}
|