|
@@ -198,9 +198,40 @@ static const char* cReadString() {
|
|
|
|
|
|
static DataType cExpression();
|
|
static DataType cExpression();
|
|
|
|
|
|
|
|
+static void cLoadRef(DataType type) {
|
|
|
|
+ if(dtIsPointer(type)) {
|
|
|
|
+ cAddOperation(OP_REFERENCE);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ switch(type.type) {
|
|
|
|
+ DT_OPERATION(LOAD);
|
|
|
|
+ case DT_STRUCT:
|
|
|
|
+ {
|
|
|
|
+ Struct* st = dtGetStruct(&structs, type);
|
|
|
|
+ if(st == NULL) {
|
|
|
|
+ cError("compiler struct error");
|
|
|
|
+ }
|
|
|
|
+ cAddIntOperation(OP_LOAD, dtGetSize(type, &structs));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ default: cError("cannot load type %s", cGetName(type));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cUnpack(DataType dt) {
|
|
|
|
+ if(dtRemoveVariable(&dt)) {
|
|
|
|
+ cLoadRef(dt);
|
|
|
|
+ }
|
|
|
|
+ return dt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cUnpackedExpression() {
|
|
|
|
+ return cUnpack(cExpression());
|
|
|
|
+}
|
|
|
|
+
|
|
static void cCallFunctionArguments(Function* f) {
|
|
static void cCallFunctionArguments(Function* f) {
|
|
while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(fAddArgument(f, dt, &structs)) {
|
|
if(fAddArgument(f, dt, &structs)) {
|
|
cTooMuchArguments();
|
|
cTooMuchArguments();
|
|
}
|
|
}
|
|
@@ -239,7 +270,7 @@ static void cWalkStruct(Variable* v) {
|
|
cError("[] need a pointer");
|
|
cError("[] need a pointer");
|
|
}
|
|
}
|
|
cAddOperation(OP_REFERENCE);
|
|
cAddOperation(OP_REFERENCE);
|
|
- DataType index = cExpression();
|
|
|
|
|
|
+ DataType index = cUnpackedExpression();
|
|
if(!dtCompare(index, dtInt())) {
|
|
if(!dtCompare(index, dtInt())) {
|
|
cError("array index must be an int");
|
|
cError("array index must be an int");
|
|
}
|
|
}
|
|
@@ -290,26 +321,6 @@ static void cReference(Variable* v, int dimension) {
|
|
cWalkStruct(v);
|
|
cWalkStruct(v);
|
|
}
|
|
}
|
|
|
|
|
|
-static void cLoadRef(Variable* v) {
|
|
|
|
- if(dtIsPointer(v->type)) {
|
|
|
|
- cAddOperation(OP_LOAD_POINTER);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- switch(v->type.type) {
|
|
|
|
- DT_OPERATION(LOAD);
|
|
|
|
- case DT_STRUCT:
|
|
|
|
- {
|
|
|
|
- Struct* st = dtGetStruct(&structs, v->type);
|
|
|
|
- if(st == NULL) {
|
|
|
|
- cError("compiler struct error");
|
|
|
|
- }
|
|
|
|
- cAddIntOperation(OP_LOAD, dtGetSize(v->type, &structs));
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- default: cError("cannot load type %s", cGetName(v->type));
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void cStore(Variable* v, DataType dt, const char* name) {
|
|
static void cStore(Variable* v, DataType dt, const char* name) {
|
|
if(!dtCompare(v->type, dt)) {
|
|
if(!dtCompare(v->type, dt)) {
|
|
cInvalidOperation(v->type, dt, name);
|
|
cInvalidOperation(v->type, dt, name);
|
|
@@ -324,14 +335,6 @@ static void cStore(Variable* v, DataType dt, const char* name) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
|
- if(!dtCompare(v->type, dtInt())) {
|
|
|
|
- cError("%s needs an int", name);
|
|
|
|
- }
|
|
|
|
- cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
|
|
|
|
- return dtInt();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static DataType cLiteral() {
|
|
static DataType cLiteral() {
|
|
const char* literal = cReadString();
|
|
const char* literal = cReadString();
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
@@ -345,14 +348,15 @@ static DataType cLiteral() {
|
|
if(vsSearch(&vars, &v, literal)) {
|
|
if(vsSearch(&vars, &v, literal)) {
|
|
cNotDeclared(literal);
|
|
cNotDeclared(literal);
|
|
}
|
|
}
|
|
- cReference(&v, 0);
|
|
|
|
|
|
+ cAddIntOperation(OP_DEREFERENCE_VAR, v.address);
|
|
|
|
+ /*cWalkStruct(&v);
|
|
|
|
+
|
|
if(cConsumeTokenIf(T_INCREMENT)) {
|
|
if(cConsumeTokenIf(T_INCREMENT)) {
|
|
return cPostChange(&v, 1, "++");
|
|
return cPostChange(&v, 1, "++");
|
|
} else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
} else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
return cPostChange(&v, -1, "--");
|
|
return cPostChange(&v, -1, "--");
|
|
- }
|
|
|
|
- cLoadRef(&v);
|
|
|
|
- return v.type;
|
|
|
|
|
|
+ }*/
|
|
|
|
+ return dtToVariable(v.type);
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cBracketPrimary() {
|
|
static DataType cBracketPrimary() {
|
|
@@ -361,20 +365,49 @@ static DataType cBracketPrimary() {
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static DataType cExtendType(DataType dt) {
|
|
|
|
+ while(cConsumeTokenIf(T_MUL)) {
|
|
|
|
+ dt = dtDereference(dt);
|
|
|
|
+ }
|
|
|
|
+ return dt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cReadType() {
|
|
|
|
+ DataType dt = dtVoid();
|
|
|
|
+ Token t = cReadTokenAndLine();
|
|
|
|
+ switch(t) {
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+ return cExtendType(dt);
|
|
|
|
+}
|
|
|
|
+
|
|
static DataType cAllocArray() {
|
|
static DataType cAllocArray() {
|
|
- cConsumeToken(T_INT);
|
|
|
|
|
|
+ DataType dt = cReadType();
|
|
cConsumeToken(T_OPEN_SQUARE_BRACKET);
|
|
cConsumeToken(T_OPEN_SQUARE_BRACKET);
|
|
- DataType index = cExpression();
|
|
|
|
|
|
+ DataType index = cUnpackedExpression();
|
|
if(!dtCompare(index, dtInt())) {
|
|
if(!dtCompare(index, dtInt())) {
|
|
cError("array size must be an int");
|
|
cError("array size must be an int");
|
|
}
|
|
}
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
- cAddIntOperation(OP_NEW, dtGetSize(dtInt(), &structs));
|
|
|
|
- return dtToArray(dtInt(), 1);
|
|
|
|
|
|
+ cAddIntOperation(OP_NEW, dtGetSize(dt, &structs));
|
|
|
|
+ return dtDereference(dt);
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cLength() {
|
|
static DataType cLength() {
|
|
- DataType pointer = cExpression();
|
|
|
|
|
|
+ DataType pointer = cUnpackedExpression();
|
|
if(!dtIsPointer(pointer)) {
|
|
if(!dtIsPointer(pointer)) {
|
|
cError("length expects a pointer");
|
|
cError("length expects a pointer");
|
|
}
|
|
}
|
|
@@ -397,83 +430,117 @@ static DataType cPrimary() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static DataType cPreChange(int change, const char* name) {
|
|
|
|
|
|
+static void cPostChange(DataType* dt, int change, const char* name) {
|
|
|
|
+ if(!dtRemoveVariable(dt) || !dtCompare(*dt, dtInt())) {
|
|
|
|
+ cError("%s needs an int reference", name);
|
|
|
|
+ }
|
|
|
|
+ cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cStructAccess(DataType dt, int pointers) {
|
|
|
|
+ Struct* st = dtGetStruct(&structs, dt);
|
|
|
|
+ if(st == NULL || dt.pointers != pointers) {
|
|
|
|
+ cError(pointers == 0 ? ". expects a struct" : "-> expects a struct*");
|
|
|
|
+ }
|
|
cConsumeToken(T_LITERAL);
|
|
cConsumeToken(T_LITERAL);
|
|
- const char* literal = cReadString();
|
|
|
|
- Variable v;
|
|
|
|
- if(vsSearch(&vars, &v, literal)) {
|
|
|
|
- cNotDeclared(literal);
|
|
|
|
|
|
+ const char* name = cReadString();
|
|
|
|
+ Variable inner;
|
|
|
|
+ if(vSearchStruct(&inner, &structs, st, name)) {
|
|
|
|
+ cError("%s has no member %s", st->name, name);
|
|
}
|
|
}
|
|
- cReference(&v, 0);
|
|
|
|
- if(!dtCompare(v.type, dtInt())) {
|
|
|
|
- cError("%s needs an int", name);
|
|
|
|
|
|
+ if(inner.address > 0) {
|
|
|
|
+ cAddIntOperation(OP_PUSH_INT, inner.address);
|
|
|
|
+ cAddOperation(OP_ADD_REFERENCE);
|
|
|
|
+ }
|
|
|
|
+ return dtToVariable(inner.type);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cAccess() {
|
|
|
|
+ DataType dt = cPrimary();
|
|
|
|
+ while(true) {
|
|
|
|
+ if(cConsumeTokenIf(T_INCREMENT)) {
|
|
|
|
+ cPostChange(&dt, 1, "++");
|
|
|
|
+ } else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
|
|
+ cPostChange(&dt, -1, "--");
|
|
|
|
+ } else if(cConsumeTokenIf(T_POINT)) {
|
|
|
|
+ if(!dtRemoveVariable(&dt)) {
|
|
|
|
+ cError(". expects a reference");
|
|
|
|
+ }
|
|
|
|
+ dt = cStructAccess(dt, 0);
|
|
|
|
+ } else if(cConsumeTokenIf(T_ARROW)) {
|
|
|
|
+ dt = cStructAccess(cUnpack(dt), 1);
|
|
|
|
+ } else if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
|
|
|
|
+ dt = cUnpack(dt);
|
|
|
|
+ if(!dtIsPointer(dt)) {
|
|
|
|
+ cError("[] needs a pointer");
|
|
|
|
+ }
|
|
|
|
+ DataType index = cUnpackedExpression();
|
|
|
|
+ if(!dtCompare(index, dtInt())) {
|
|
|
|
+ cError("array index must be an int");
|
|
|
|
+ }
|
|
|
|
+ cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
|
+ cAddOperation(OP_ADD_REFERENCE);
|
|
|
|
+ dt = dtToVariable(dtReference(dt));
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return dt;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static DataType cPreChange(DataType dt, int change, const char* name) {
|
|
|
|
+ if(!dtRemoveVariable(&dt) || !dtCompare(dt, dtInt())) {
|
|
|
|
+ cError("%s needs an int reference", name);
|
|
}
|
|
}
|
|
cAddByteOperation(OP_PUSH_PRE_INT_CHANGE, change);
|
|
cAddByteOperation(OP_PUSH_PRE_INT_CHANGE, change);
|
|
- return dtInt();
|
|
|
|
|
|
+ return dt;
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cPreUnary() {
|
|
static DataType cPreUnary() {
|
|
- if(cConsumeTokenIf(T_SUB)) {
|
|
|
|
- DataType result = cPrimary();
|
|
|
|
- if(dtCompare(result, dtInt())) {
|
|
|
|
|
|
+ if(cConsumeTokenIf(T_INCREMENT)) {
|
|
|
|
+ return cPreChange(cPreUnary(), 1, "++");
|
|
|
|
+ } else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
|
|
+ return cPreChange(cPreUnary(), -1, "--");
|
|
|
|
+ } else if(cConsumeTokenIf(T_SUB)) {
|
|
|
|
+ DataType dt = cUnpack(cPreUnary());
|
|
|
|
+ if(dtCompare(dt, dtInt())) {
|
|
cAddOperation(OP_INVERT_SIGN_INT);
|
|
cAddOperation(OP_INVERT_SIGN_INT);
|
|
- } else if(dtCompare(result, dtFloat())) {
|
|
|
|
|
|
+ } else if(dtCompare(dt, dtFloat())) {
|
|
cAddOperation(OP_INVERT_SIGN_FLOAT);
|
|
cAddOperation(OP_INVERT_SIGN_FLOAT);
|
|
} else {
|
|
} else {
|
|
- cError("cannot invert sign of %s", cGetName(result));
|
|
|
|
|
|
+ cError("cannot invert sign of %s", cGetName(dt));
|
|
}
|
|
}
|
|
- return result;
|
|
|
|
- } else if(cConsumeTokenIf(T_INCREMENT)) {
|
|
|
|
- return cPreChange(1, "++");
|
|
|
|
- } else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
|
|
- return cPreChange(-1, "--");
|
|
|
|
|
|
+ return dt;
|
|
} else if(cConsumeTokenIf(T_NOT)) {
|
|
} else if(cConsumeTokenIf(T_NOT)) {
|
|
- int counter = 1;
|
|
|
|
- while(cConsumeTokenIf(T_NOT)) {
|
|
|
|
- counter++;
|
|
|
|
- }
|
|
|
|
- DataType result = cPrimary();
|
|
|
|
- if(!dtCompare(result, dtBool())) {
|
|
|
|
- cError("! needs a bool not %s", cGetName(result));
|
|
|
|
|
|
+ DataType dt = cPreUnary();
|
|
|
|
+ if(!dtCompare(dt, dtBool())) {
|
|
|
|
+ cError("! needs a bool not %s", cGetName(dt));
|
|
}
|
|
}
|
|
cAddOperation(OP_NOT);
|
|
cAddOperation(OP_NOT);
|
|
- if((counter & 1) == 0) {
|
|
|
|
- cAddOperation(OP_NOT);
|
|
|
|
- }
|
|
|
|
- return dtBool();
|
|
|
|
|
|
+ return dt;
|
|
} else if(cConsumeTokenIf(T_BIT_NOT)) {
|
|
} else if(cConsumeTokenIf(T_BIT_NOT)) {
|
|
- DataType result = cPrimary();
|
|
|
|
- if(dtCompare(result, dtInt())) {
|
|
|
|
- cAddOperation(OP_BIT_NOT);
|
|
|
|
- } else {
|
|
|
|
- cError("~ needs an int not %s", cGetName(result));
|
|
|
|
|
|
+ DataType dt = cPreUnary();
|
|
|
|
+ if(!dtCompare(dt, dtInt())) {
|
|
|
|
+ cError("~ needs an int not %s", cGetName(dt));
|
|
}
|
|
}
|
|
- return result;
|
|
|
|
|
|
+ cAddOperation(OP_BIT_NOT);
|
|
|
|
+ return dt;
|
|
} else if(cConsumeTokenIf(T_BIT_AND)) {
|
|
} else if(cConsumeTokenIf(T_BIT_AND)) {
|
|
- cConsumeToken(T_LITERAL);
|
|
|
|
- const char* literal = cReadString();
|
|
|
|
- Variable v;
|
|
|
|
- if(vsSearch(&vars, &v, literal)) {
|
|
|
|
- cNotDeclared(literal);
|
|
|
|
|
|
+ DataType dt = cPreUnary();
|
|
|
|
+ if(!dtRemoveVariable(&dt)) {
|
|
|
|
+ cError("& needs a reference");
|
|
}
|
|
}
|
|
- cReference(&v, 0);
|
|
|
|
- return dtDereference(v.type);
|
|
|
|
|
|
+ return dtDereference(dt);
|
|
} else if(cConsumeTokenIf(T_MUL)) {
|
|
} else if(cConsumeTokenIf(T_MUL)) {
|
|
- int c = 1;
|
|
|
|
- while(cConsumeTokenIf(T_MUL)) {
|
|
|
|
- c++;
|
|
|
|
- }
|
|
|
|
- cConsumeToken(T_LITERAL);
|
|
|
|
- const char* literal = cReadString();
|
|
|
|
- Variable v;
|
|
|
|
- if(vsSearch(&vars, &v, literal)) {
|
|
|
|
- cNotDeclared(literal);
|
|
|
|
|
|
+ DataType dt = cPreUnary();
|
|
|
|
+ if(!dtIsPointer(dt)) {
|
|
|
|
+ cError("* expects a pointer");
|
|
}
|
|
}
|
|
- cReference(&v, c);
|
|
|
|
- cLoadRef(&v);
|
|
|
|
- return v.type;
|
|
|
|
|
|
+ dt = dtReference(dt);
|
|
|
|
+ cAddOperation(OP_REFERENCE);
|
|
|
|
+ return dt;
|
|
}
|
|
}
|
|
- return cPrimary();
|
|
|
|
|
|
+ return cAccess();
|
|
}
|
|
}
|
|
|
|
|
|
static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
|
|
static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
|
|
@@ -498,11 +565,14 @@ static DataType cMul() {
|
|
DataType a = cPreUnary();
|
|
DataType a = cPreUnary();
|
|
while(true) {
|
|
while(true) {
|
|
if(cConsumeTokenIf(T_MUL)) {
|
|
if(cConsumeTokenIf(T_MUL)) {
|
|
- cAddTypeOperation(a, cPreUnary(), &TYPED_MUL);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cPreUnary()), &TYPED_MUL);
|
|
} else if(cConsumeTokenIf(T_DIV)) {
|
|
} else if(cConsumeTokenIf(T_DIV)) {
|
|
- cAddTypeOperation(a, cPreUnary(), &TYPED_DIV);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cPreUnary()), &TYPED_DIV);
|
|
} else if(cConsumeTokenIf(T_MOD)) {
|
|
} else if(cConsumeTokenIf(T_MOD)) {
|
|
- cAddTypeOperation(a, cPreUnary(), &TYPED_MOD);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cPreUnary()), &TYPED_MOD);
|
|
} else {
|
|
} else {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -514,9 +584,11 @@ static DataType cAdd() {
|
|
DataType a = cMul();
|
|
DataType a = cMul();
|
|
while(true) {
|
|
while(true) {
|
|
if(cConsumeTokenIf(T_ADD)) {
|
|
if(cConsumeTokenIf(T_ADD)) {
|
|
- cAddTypeOperation(a, cMul(), &TYPED_ADD);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cMul()), &TYPED_ADD);
|
|
} else if(cConsumeTokenIf(T_SUB)) {
|
|
} else if(cConsumeTokenIf(T_SUB)) {
|
|
- cAddTypeOperation(a, cMul(), &TYPED_SUB);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cMul()), &TYPED_SUB);
|
|
} else {
|
|
} else {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -528,9 +600,11 @@ static DataType cShift() {
|
|
DataType a = cAdd();
|
|
DataType a = cAdd();
|
|
while(true) {
|
|
while(true) {
|
|
if(cConsumeTokenIf(T_LEFT_SHIFT)) {
|
|
if(cConsumeTokenIf(T_LEFT_SHIFT)) {
|
|
- cAddTypeOperation(a, cAdd(), &TYPED_LEFT_SHIFT);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cAdd()), &TYPED_LEFT_SHIFT);
|
|
} else if(cConsumeTokenIf(T_RIGHT_SHIFT)) {
|
|
} else if(cConsumeTokenIf(T_RIGHT_SHIFT)) {
|
|
- cAddTypeOperation(a, cAdd(), &TYPED_RIGHT_SHIFT);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cAdd()), &TYPED_RIGHT_SHIFT);
|
|
} else {
|
|
} else {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -542,17 +616,21 @@ static DataType cComparison() {
|
|
DataType a = cShift();
|
|
DataType a = cShift();
|
|
while(true) {
|
|
while(true) {
|
|
if(cConsumeTokenIf(T_LESS)) {
|
|
if(cConsumeTokenIf(T_LESS)) {
|
|
- cAddTypeOperation(a, cShift(), &TYPED_LESS);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cShift()), &TYPED_LESS);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else if(cConsumeTokenIf(T_LESS_EQUAL)) {
|
|
} else if(cConsumeTokenIf(T_LESS_EQUAL)) {
|
|
- cAddTypeOperation(a, cShift(), &TYPED_LESS_EQUAL);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cShift()), &TYPED_LESS_EQUAL);
|
|
cAddOperation(OP_NOT);
|
|
cAddOperation(OP_NOT);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else if(cConsumeTokenIf(T_GREATER)) {
|
|
} else if(cConsumeTokenIf(T_GREATER)) {
|
|
- cAddTypeOperation(a, cShift(), &TYPED_GREATER);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cShift()), &TYPED_GREATER);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
|
|
} else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
|
|
- cAddTypeOperation(a, cShift(), &TYPED_GREATER_EQUAL);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cShift()), &TYPED_GREATER_EQUAL);
|
|
cAddOperation(OP_NOT);
|
|
cAddOperation(OP_NOT);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else {
|
|
} else {
|
|
@@ -566,10 +644,12 @@ static DataType cEqual() {
|
|
DataType a = cComparison();
|
|
DataType a = cComparison();
|
|
while(true) {
|
|
while(true) {
|
|
if(cConsumeTokenIf(T_EQUAL)) {
|
|
if(cConsumeTokenIf(T_EQUAL)) {
|
|
- cAddTypeOperation(a, cComparison(), &TYPED_EQUAL);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cComparison()), &TYPED_EQUAL);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else if(cConsumeTokenIf(T_NOT_EQUAL)) {
|
|
} else if(cConsumeTokenIf(T_NOT_EQUAL)) {
|
|
- cAddTypeOperation(a, cComparison(), &TYPED_NOT_EQUAL);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cComparison()), &TYPED_NOT_EQUAL);
|
|
cAddOperation(OP_NOT);
|
|
cAddOperation(OP_NOT);
|
|
a = dtBool();
|
|
a = dtBool();
|
|
} else {
|
|
} else {
|
|
@@ -582,8 +662,8 @@ static DataType cEqual() {
|
|
static DataType cBitAnd() {
|
|
static DataType cBitAnd() {
|
|
DataType a = cEqual();
|
|
DataType a = cEqual();
|
|
while(cConsumeTokenIf(T_BIT_AND)) {
|
|
while(cConsumeTokenIf(T_BIT_AND)) {
|
|
- DataType b = cEqual();
|
|
|
|
- cAddTypeOperation(a, b, &TYPED_BIT_AND);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cEqual()), &TYPED_BIT_AND);
|
|
}
|
|
}
|
|
return a;
|
|
return a;
|
|
}
|
|
}
|
|
@@ -591,8 +671,8 @@ static DataType cBitAnd() {
|
|
static DataType cBitXor() {
|
|
static DataType cBitXor() {
|
|
DataType a = cBitAnd();
|
|
DataType a = cBitAnd();
|
|
while(cConsumeTokenIf(T_BIT_XOR)) {
|
|
while(cConsumeTokenIf(T_BIT_XOR)) {
|
|
- DataType b = cBitAnd();
|
|
|
|
- cAddTypeOperation(a, b, &TYPED_BIT_XOR);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cBitAnd()), &TYPED_BIT_XOR);
|
|
}
|
|
}
|
|
return a;
|
|
return a;
|
|
}
|
|
}
|
|
@@ -600,8 +680,8 @@ static DataType cBitXor() {
|
|
static DataType cBitOr() {
|
|
static DataType cBitOr() {
|
|
DataType a = cBitXor();
|
|
DataType a = cBitXor();
|
|
while(cConsumeTokenIf(T_BIT_OR)) {
|
|
while(cConsumeTokenIf(T_BIT_OR)) {
|
|
- DataType b = cBitXor();
|
|
|
|
- cAddTypeOperation(a, b, &TYPED_BIT_OR);
|
|
|
|
|
|
+ a = cUnpack(a);
|
|
|
|
+ cAddTypeOperation(a, cUnpack(cBitXor()), &TYPED_BIT_OR);
|
|
}
|
|
}
|
|
return a;
|
|
return a;
|
|
}
|
|
}
|
|
@@ -609,9 +689,10 @@ static DataType cBitOr() {
|
|
static DataType cAnd() {
|
|
static DataType cAnd() {
|
|
DataType a = cBitOr();
|
|
DataType a = cBitOr();
|
|
while(cConsumeTokenIf(T_AND)) {
|
|
while(cConsumeTokenIf(T_AND)) {
|
|
|
|
+ a = cUnpack(a);
|
|
cAddOperation(OP_PEEK_FALSE_GOTO);
|
|
cAddOperation(OP_PEEK_FALSE_GOTO);
|
|
int p = cReserveInt();
|
|
int p = cReserveInt();
|
|
- DataType b = cBitOr();
|
|
|
|
|
|
+ DataType b = cUnpack(cBitOr());
|
|
if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
cInvalidOperation(a, b, "&&");
|
|
cInvalidOperation(a, b, "&&");
|
|
}
|
|
}
|
|
@@ -624,9 +705,10 @@ static DataType cAnd() {
|
|
static DataType cOr() {
|
|
static DataType cOr() {
|
|
DataType a = cAnd();
|
|
DataType a = cAnd();
|
|
while(cConsumeTokenIf(T_OR)) {
|
|
while(cConsumeTokenIf(T_OR)) {
|
|
|
|
+ a = cUnpack(a);
|
|
cAddOperation(OP_PEEK_TRUE_GOTO);
|
|
cAddOperation(OP_PEEK_TRUE_GOTO);
|
|
int p = cReserveInt();
|
|
int p = cReserveInt();
|
|
- DataType b = cAnd();
|
|
|
|
|
|
+ DataType b = cUnpack(cAnd());
|
|
if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
cInvalidOperation(a, b, "||");
|
|
cInvalidOperation(a, b, "||");
|
|
}
|
|
}
|
|
@@ -642,8 +724,8 @@ static DataType cExpression() {
|
|
|
|
|
|
static void cOperationSet(Variable* v, const TypedOp* op) {
|
|
static void cOperationSet(Variable* v, const TypedOp* op) {
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
- cLoadRef(v);
|
|
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ cLoadRef(v->type);
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
cAddTypeOperation(v->type, dt, op);
|
|
cAddTypeOperation(v->type, dt, op);
|
|
cStore(v, dt, "=");
|
|
cStore(v, dt, "=");
|
|
}
|
|
}
|
|
@@ -655,13 +737,6 @@ static void cAddPostLineChange(Variable* v, int change, const char* name) {
|
|
cAddByteOperation(OP_INT_CHANGE, change);
|
|
cAddByteOperation(OP_INT_CHANGE, change);
|
|
}
|
|
}
|
|
|
|
|
|
-static DataType cExtendType(DataType dt) {
|
|
|
|
- while(cConsumeTokenIf(T_MUL)) {
|
|
|
|
- dt = dtDereference(dt);
|
|
|
|
- }
|
|
|
|
- return dt;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void cDeclareStruct(Struct* st) {
|
|
static void cDeclareStruct(Struct* st) {
|
|
DataType dt = cExtendType(dtStruct(st));
|
|
DataType dt = cExtendType(dtStruct(st));
|
|
cConsumeToken(T_LITERAL);
|
|
cConsumeToken(T_LITERAL);
|
|
@@ -673,7 +748,7 @@ static void cDeclareStruct(Struct* st) {
|
|
if(dtIsPointer(dt)) {
|
|
if(dtIsPointer(dt)) {
|
|
cConsumeToken(T_SET);
|
|
cConsumeToken(T_SET);
|
|
cReference(vp, 0);
|
|
cReference(vp, 0);
|
|
- cStore(vp, cExpression(), "=");
|
|
|
|
|
|
+ cStore(vp, cUnpackedExpression(), "=");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -685,7 +760,7 @@ static void cLineVariable(const char* name, int dimension) {
|
|
cReference(&v, dimension);
|
|
cReference(&v, dimension);
|
|
Token t = cReadTokenAndLine();
|
|
Token t = cReadTokenAndLine();
|
|
switch(t) {
|
|
switch(t) {
|
|
- case T_SET: cStore(&v, cExpression(), "="); break;
|
|
|
|
|
|
+ case T_SET: cStore(&v, cUnpackedExpression(), "="); break;
|
|
case T_ADD_SET: cOperationSet(&v, &TYPED_ADD); break;
|
|
case T_ADD_SET: cOperationSet(&v, &TYPED_ADD); break;
|
|
case T_SUB_SET: cOperationSet(&v, &TYPED_SUB); break;
|
|
case T_SUB_SET: cOperationSet(&v, &TYPED_SUB); break;
|
|
case T_MUL_SET: cOperationSet(&v, &TYPED_MUL); break;
|
|
case T_MUL_SET: cOperationSet(&v, &TYPED_MUL); break;
|
|
@@ -755,7 +830,7 @@ static void cReturn() {
|
|
cAddReturn(OP_RETURN);
|
|
cAddReturn(OP_RETURN);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(!dtCompare(dt, returnType)) {
|
|
if(!dtCompare(dt, returnType)) {
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
}
|
|
}
|
|
@@ -772,7 +847,7 @@ static void cReturn() {
|
|
}
|
|
}
|
|
|
|
|
|
static void cPrint() {
|
|
static void cPrint() {
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(dtIsPointer(dt)) {
|
|
if(dtIsPointer(dt)) {
|
|
cAddOperation(OP_PRINT_POINTER);
|
|
cAddOperation(OP_PRINT_POINTER);
|
|
cConsumeToken(T_SEMICOLON);
|
|
cConsumeToken(T_SEMICOLON);
|
|
@@ -787,7 +862,7 @@ static void cPrint() {
|
|
|
|
|
|
static void cIf() {
|
|
static void cIf() {
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(!dtCompare(dt, dtBool())) {
|
|
if(!dtCompare(dt, dtBool())) {
|
|
cError("if expects a bool not %s", cGetName(dt));
|
|
cError("if expects a bool not %s", cGetName(dt));
|
|
}
|
|
}
|
|
@@ -822,7 +897,7 @@ static void cConsumeBreaks(int start, int address) {
|
|
static void cWhile() {
|
|
static void cWhile() {
|
|
int start = code->length;
|
|
int start = code->length;
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(!dtCompare(dt, dtBool())) {
|
|
if(!dtCompare(dt, dtBool())) {
|
|
cError("while expects a bool not %s", cGetName(dt));
|
|
cError("while expects a bool not %s", cGetName(dt));
|
|
}
|
|
}
|
|
@@ -852,7 +927,7 @@ static void cDeclare(DataType dt) {
|
|
Variable* vp = vsAdd(&vars, var, dt, &structs);
|
|
Variable* vp = vsAdd(&vars, var, dt, &structs);
|
|
cConsumeToken(T_SET);
|
|
cConsumeToken(T_SET);
|
|
cReference(vp, 0);
|
|
cReference(vp, 0);
|
|
- cStore(vp, cExpression(), "=");
|
|
|
|
|
|
+ cStore(vp, cUnpackedExpression(), "=");
|
|
}
|
|
}
|
|
|
|
|
|
static void cAddPreLineChange(int change, const char* name) {
|
|
static void cAddPreLineChange(int change, const char* name) {
|
|
@@ -867,7 +942,7 @@ static void cAddPreLineChange(int change, const char* name) {
|
|
}
|
|
}
|
|
|
|
|
|
static void cDelete() {
|
|
static void cDelete() {
|
|
- DataType pointer = cExpression();
|
|
|
|
|
|
+ DataType pointer = cUnpackedExpression();
|
|
if(!dtIsPointer(pointer)) {
|
|
if(!dtIsPointer(pointer)) {
|
|
cError("delete expects a pointer");
|
|
cError("delete expects a pointer");
|
|
}
|
|
}
|
|
@@ -905,7 +980,7 @@ static void cFor() {
|
|
cLineExpression(cReadTokenAndLine());
|
|
cLineExpression(cReadTokenAndLine());
|
|
cConsumeToken(T_SEMICOLON);
|
|
cConsumeToken(T_SEMICOLON);
|
|
int startCheck = code->length;
|
|
int startCheck = code->length;
|
|
- DataType dt = cExpression();
|
|
|
|
|
|
+ DataType dt = cUnpackedExpression();
|
|
if(!dtCompare(dt, dtBool())) {
|
|
if(!dtCompare(dt, dtBool())) {
|
|
cError("for expects a bool not %s", cGetName(dt));
|
|
cError("for expects a bool not %s", cGetName(dt));
|
|
}
|
|
}
|
|
@@ -1108,25 +1183,7 @@ static void cStruct() {
|
|
DataType self = dtStruct(st);
|
|
DataType self = dtStruct(st);
|
|
cConsumeToken(T_OPEN_CURVED_BRACKET);
|
|
cConsumeToken(T_OPEN_CURVED_BRACKET);
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
- Token t = cReadTokenAndLine();
|
|
|
|
- DataType dt = dtVoid();
|
|
|
|
- switch(t) {
|
|
|
|
- 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);
|
|
|
|
|
|
+ DataType dt = cReadType();
|
|
if(dtCompare(dt, self)) {
|
|
if(dtCompare(dt, self)) {
|
|
cError("struct %s contains itself", name);
|
|
cError("struct %s contains itself", name);
|
|
}
|
|
}
|