|
@@ -26,6 +26,7 @@ static char error[ERROR_LENGTH] = {'\0'};
|
|
|
static ByteCode* code;
|
|
|
|
|
|
static int16 line = 1;
|
|
|
+static bool onLine = false;
|
|
|
|
|
|
static Variables vars;
|
|
|
static Functions functions;
|
|
@@ -262,100 +263,30 @@ static DataType cCallFunction(const char* name) {
|
|
|
return found->returnType;
|
|
|
}
|
|
|
|
|
|
-static void cWalkStruct(Variable* v) {
|
|
|
- int offset = 0;
|
|
|
- while(true) {
|
|
|
- if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
|
|
|
- if(!dtIsPointer(v->type)) {
|
|
|
- cError("[] need a pointer");
|
|
|
- }
|
|
|
- cAddOperation(OP_REFERENCE);
|
|
|
- DataType index = cUnpackedExpression();
|
|
|
- if(!dtCompare(index, dtInt())) {
|
|
|
- cError("array index must be an int");
|
|
|
- }
|
|
|
- cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
- cAddOperation(OP_ADD_REFERENCE);
|
|
|
- v->type = dtReference(v->type);
|
|
|
- }
|
|
|
- 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) {
|
|
|
- cError("%s is not a %s but %s", v->name,
|
|
|
- pointers ? "struct*" : "struct", 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;
|
|
|
- }
|
|
|
- if(offset > 0) {
|
|
|
- cAddIntOperation(OP_PUSH_INT, offset);
|
|
|
- cAddOperation(OP_ADD_REFERENCE);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void cReference(Variable* v, int dimension) {
|
|
|
- cAddIntOperation(OP_DEREFERENCE_VAR, v->address);
|
|
|
- while(dimension > 0) {
|
|
|
- if(!dtIsPointer(v->type)) {
|
|
|
- cError("too many *");
|
|
|
- }
|
|
|
- v->type = dtReference(v->type);
|
|
|
- dimension--;
|
|
|
- cAddOperation(OP_REFERENCE);
|
|
|
+static void cStore(DataType left, DataType right, const char* name) {
|
|
|
+ if(!dtCompare(left, right)) {
|
|
|
+ cInvalidOperation(left, right, name);
|
|
|
}
|
|
|
- cWalkStruct(v);
|
|
|
-}
|
|
|
-
|
|
|
-static void cStore(Variable* v, DataType dt, const char* name) {
|
|
|
- if(!dtCompare(v->type, dt)) {
|
|
|
- cInvalidOperation(v->type, dt, name);
|
|
|
- }
|
|
|
- if(dtIsPointer(v->type)) {
|
|
|
+ if(dtIsPointer(left)) {
|
|
|
cAddOperation(OP_STORE_POINTER);
|
|
|
return;
|
|
|
}
|
|
|
- switch(v->type.type) {
|
|
|
+ switch(left.type) {
|
|
|
DT_OPERATION(STORE);
|
|
|
- default: cError("cannot store type %s", cGetName(v->type));
|
|
|
+ default: cError("cannot store type %s", cGetName(left));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static DataType cLiteral() {
|
|
|
const char* literal = cReadString();
|
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
- DataType dt = cCallFunction(literal);
|
|
|
- if(dtCompare(dt, dtVoid())) {
|
|
|
- cError("function returns void");
|
|
|
- }
|
|
|
- return dt;
|
|
|
+ return cCallFunction(literal);
|
|
|
}
|
|
|
Variable v;
|
|
|
if(vsSearch(&vars, &v, literal)) {
|
|
|
cNotDeclared(literal);
|
|
|
}
|
|
|
cAddIntOperation(OP_DEREFERENCE_VAR, v.address);
|
|
|
-
|
|
|
-
|
|
|
- if(cConsumeTokenIf(T_INCREMENT)) {
|
|
|
- return cPostChange(&v, 1, "++");
|
|
|
- } else if(cConsumeTokenIf(T_DECREMENT)) {
|
|
|
- return cPostChange(&v, -1, "--");
|
|
|
- }*/
|
|
|
return dtToVariable(v.type);
|
|
|
}
|
|
|
|
|
@@ -433,8 +364,12 @@ static DataType cPrimary() {
|
|
|
static void cPostChange(DataType* dt, int change, const char* name) {
|
|
|
if(!dtRemoveVariable(dt) || !dtCompare(*dt, dtInt())) {
|
|
|
cError("%s needs an int reference", name);
|
|
|
+ } else if(onLine) {
|
|
|
+ cAddByteOperation(OP_INT_CHANGE, change);
|
|
|
+ *dt = dtVoid();
|
|
|
+ } else {
|
|
|
+ cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
|
|
|
}
|
|
|
- cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
|
|
|
}
|
|
|
|
|
|
static DataType cStructAccess(DataType dt, int pointers) {
|
|
@@ -492,6 +427,10 @@ static DataType cPreChange(DataType dt, int change, const char* name) {
|
|
|
if(!dtRemoveVariable(&dt) || !dtCompare(dt, dtInt())) {
|
|
|
cError("%s needs an int reference", name);
|
|
|
}
|
|
|
+ if(onLine) {
|
|
|
+ cAddByteOperation(OP_INT_CHANGE, change);
|
|
|
+ return dtVoid();
|
|
|
+ }
|
|
|
cAddByteOperation(OP_PUSH_PRE_INT_CHANGE, change);
|
|
|
return dt;
|
|
|
}
|
|
@@ -722,16 +661,16 @@ static DataType cExpression() {
|
|
|
return cOr();
|
|
|
}
|
|
|
|
|
|
-static void cOperationSet(Variable* v, const TypedOp* op) {
|
|
|
+static void cOperationSet(DataType left, const TypedOp* op) {
|
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- cLoadRef(v->type);
|
|
|
- DataType dt = cUnpackedExpression();
|
|
|
- cAddTypeOperation(v->type, dt, op);
|
|
|
- cStore(v, dt, "=");
|
|
|
+ cLoadRef(left);
|
|
|
+ DataType right = cUnpackedExpression();
|
|
|
+ cAddTypeOperation(left, right, op);
|
|
|
+ cStore(left, right, "=");
|
|
|
}
|
|
|
|
|
|
-static void cAddPostLineChange(Variable* v, int change, const char* name) {
|
|
|
- if(!dtCompare(v->type, dtInt())) {
|
|
|
+static void cAddPostLineChange(DataType dt, int change, const char* name) {
|
|
|
+ if(!dtCompare(dt, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
cAddByteOperation(OP_INT_CHANGE, change);
|
|
@@ -744,67 +683,24 @@ static void cDeclareStruct(Struct* st) {
|
|
|
if(vsInScope(&vars, var)) {
|
|
|
cDeclared(var);
|
|
|
}
|
|
|
- Variable* vp = vsAdd(&vars, var, dt, &structs);
|
|
|
+ Variable* v = vsAdd(&vars, var, dt, &structs);
|
|
|
if(dtIsPointer(dt)) {
|
|
|
cConsumeToken(T_SET);
|
|
|
- cReference(vp, 0);
|
|
|
- cStore(vp, cUnpackedExpression(), "=");
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void cLineVariable(const char* name, int dimension) {
|
|
|
- Variable v;
|
|
|
- if(vsSearch(&vars, &v, name)) {
|
|
|
- cNotDeclared(name);
|
|
|
+ cAddIntOperation(OP_DEREFERENCE_VAR, v->address);
|
|
|
+ cStore(v->type, cUnpackedExpression(), "=");
|
|
|
}
|
|
|
- cReference(&v, dimension);
|
|
|
- Token t = cReadTokenAndLine();
|
|
|
- switch(t) {
|
|
|
- case T_SET: cStore(&v, cUnpackedExpression(), "="); 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_INCREMENT: cAddPostLineChange(&v, 1, "++"); break;
|
|
|
- case T_DECREMENT: cAddPostLineChange(&v, -1, "--"); break;
|
|
|
- default: cUnexpectedToken(t);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void cLineLiteral() {
|
|
|
- const char* literal = cReadString();
|
|
|
- if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
- DataType dt = cCallFunction(literal);
|
|
|
- if(!dtCompare(dt, dtVoid())) {
|
|
|
- cError("function returns %s not void", cGetName(dt));
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- Struct* st = stsSearch(&structs, literal);
|
|
|
- if(st != NULL) {
|
|
|
- cDeclareStruct(st);
|
|
|
- return;
|
|
|
- }
|
|
|
- cLineVariable(literal, 0);
|
|
|
}
|
|
|
|
|
|
-static void cLine(Token t);
|
|
|
+static void cLine();
|
|
|
|
|
|
static void cConsumeBody() {
|
|
|
int oldLine = line;
|
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
|
- Token t = cReadTokenAndLine();
|
|
|
- if(t == T_END) {
|
|
|
+ if(tPeekToken() == T_END) {
|
|
|
line = oldLine;
|
|
|
cError("unexpected end of file: non closed curved bracket");
|
|
|
}
|
|
|
- cLine(t);
|
|
|
+ cLine();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -924,21 +820,10 @@ static void cDeclare(DataType dt) {
|
|
|
if(vsInScope(&vars, var)) {
|
|
|
cDeclared(var);
|
|
|
}
|
|
|
- Variable* vp = vsAdd(&vars, var, dt, &structs);
|
|
|
+ Variable* v = vsAdd(&vars, var, dt, &structs);
|
|
|
cConsumeToken(T_SET);
|
|
|
- cReference(vp, 0);
|
|
|
- cStore(vp, cUnpackedExpression(), "=");
|
|
|
-}
|
|
|
-
|
|
|
-static void cAddPreLineChange(int change, const char* name) {
|
|
|
- cConsumeToken(T_LITERAL);
|
|
|
- const char* literal = cReadString();
|
|
|
- Variable v;
|
|
|
- if(vsSearch(&vars, &v, literal)) {
|
|
|
- cNotDeclared(literal);
|
|
|
- }
|
|
|
- cReference(&v, 0);
|
|
|
- cAddPostLineChange(&v, change, name);
|
|
|
+ cAddIntOperation(OP_DEREFERENCE_VAR, v->address);
|
|
|
+ cStore(v->type, cUnpackedExpression(), "=");
|
|
|
}
|
|
|
|
|
|
static void cDelete() {
|
|
@@ -949,26 +834,52 @@ static void cDelete() {
|
|
|
cAddOperation(OP_DELETE);
|
|
|
}
|
|
|
|
|
|
-static void cLineExpression(Token t) {
|
|
|
+static void cSetVariable() {
|
|
|
+ onLine = true;
|
|
|
+ DataType dt = cPreUnary();
|
|
|
+ onLine = false;
|
|
|
+ if(dtCompare(dt, dtVoid())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(!dtRemoveVariable(&dt)) {
|
|
|
+ cError("reference or void expected: %s", cGetName(dt));
|
|
|
+ }
|
|
|
+ Token t = cReadTokenAndLine();
|
|
|
+ switch(t) {
|
|
|
+ case T_SET: cStore(dt, cUnpackedExpression(), "="); break;
|
|
|
+ case T_ADD_SET: cOperationSet(dt, &TYPED_ADD); break;
|
|
|
+ case T_SUB_SET: cOperationSet(dt, &TYPED_SUB); break;
|
|
|
+ case T_MUL_SET: cOperationSet(dt, &TYPED_MUL); break;
|
|
|
+ case T_DIV_SET: cOperationSet(dt, &TYPED_DIV); break;
|
|
|
+ case T_MOD_SET: cOperationSet(dt, &TYPED_MOD); break;
|
|
|
+ case T_BIT_AND_SET: cOperationSet(dt, &TYPED_BIT_AND); break;
|
|
|
+ case T_BIT_OR_SET: cOperationSet(dt, &TYPED_BIT_OR); break;
|
|
|
+ case T_BIT_XOR_SET: cOperationSet(dt, &TYPED_BIT_XOR); break;
|
|
|
+ case T_LEFT_SHIFT_SET: cOperationSet(dt, &TYPED_LEFT_SHIFT); break;
|
|
|
+ case T_RIGHT_SHIFT_SET: cOperationSet(dt, &TYPED_RIGHT_SHIFT); break;
|
|
|
+ case T_INCREMENT: cAddPostLineChange(dt, 1, "++"); break;
|
|
|
+ case T_DECREMENT: cAddPostLineChange(dt, -1, "--"); break;
|
|
|
+ default: cUnexpectedToken(t);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void cLineExpression() {
|
|
|
+ int marker = tGetMarker();
|
|
|
+ Token t = cReadTokenAndLine();
|
|
|
+ if(t == T_LITERAL) {
|
|
|
+ const char* literal = cReadString();
|
|
|
+ Struct* st = stsSearch(&structs, literal);
|
|
|
+ if(st != NULL) {
|
|
|
+ cDeclareStruct(st);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
switch(t) {
|
|
|
- case T_LITERAL: cLineLiteral(); break;
|
|
|
case T_INT: cDeclare(dtInt()); break;
|
|
|
case T_BOOL: cDeclare(dtBool()); break;
|
|
|
case T_FLOAT: cDeclare(dtFloat()); break;
|
|
|
- case T_INCREMENT: cAddPreLineChange(1, "++"); break;
|
|
|
- case T_DECREMENT: cAddPreLineChange(-1, "--"); break;
|
|
|
- case T_MUL:
|
|
|
- {
|
|
|
- int c = 1;
|
|
|
- while(cConsumeTokenIf(T_MUL)) {
|
|
|
- c++;
|
|
|
- }
|
|
|
- cConsumeToken(T_LITERAL);
|
|
|
- cLineVariable(cReadString(), c);
|
|
|
- break;
|
|
|
- }
|
|
|
case T_DELETE: cDelete(); break;
|
|
|
- default: cUnexpectedToken(t);
|
|
|
+ default: tReset(marker); cSetVariable();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -977,7 +888,7 @@ static void cFor() {
|
|
|
vsEnterScope(&vars, &scope);
|
|
|
|
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
|
- cLineExpression(cReadTokenAndLine());
|
|
|
+ cLineExpression();
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
int startCheck = code->length;
|
|
|
DataType dt = cUnpackedExpression();
|
|
@@ -990,7 +901,7 @@ static void cFor() {
|
|
|
cAddOperation(OP_GOTO);
|
|
|
int beginBody = cReserveInt();
|
|
|
int startPerLoop = code->length;
|
|
|
- cLineExpression(cReadTokenAndLine());
|
|
|
+ cLineExpression();
|
|
|
cAddIntOperation(OP_GOTO, startCheck);
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
|
cSetInt(beginBody, code->length);
|
|
@@ -1028,7 +939,9 @@ static void cContinue() {
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
}
|
|
|
|
|
|
-static void cLine(Token t) {
|
|
|
+static void cLine() {
|
|
|
+ int marker = tGetMarker();
|
|
|
+ Token t = cReadTokenAndLine();
|
|
|
hasReturn = false;
|
|
|
cAddOperation(OP_LINE);
|
|
|
cAddInt16(line);
|
|
@@ -1041,7 +954,10 @@ static void cLine(Token t) {
|
|
|
case T_FOR: cFor(); break;
|
|
|
case T_BREAK: cBreak(); break;
|
|
|
case T_CONTINUE: cContinue(); break;
|
|
|
- default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
|
|
|
+ default:
|
|
|
+ tReset(marker);
|
|
|
+ cLineExpression();
|
|
|
+ cConsumeToken(T_SEMICOLON);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1245,6 +1161,7 @@ static void cAllocAndCompile() {
|
|
|
forWhileStack = 0;
|
|
|
breakIndex = 0;
|
|
|
returnType = dtVoid();
|
|
|
+ onLine = false;
|
|
|
vsInit(&vars);
|
|
|
fsInit(&functions);
|
|
|
fsInit(&functionQueue);
|