|
@@ -46,32 +46,42 @@ typedef struct {
|
|
|
Operation intOp;
|
|
|
Operation floatOp;
|
|
|
Operation boolOp;
|
|
|
+ Operation pointerOp;
|
|
|
const char* name;
|
|
|
} TypedOp;
|
|
|
|
|
|
-static const TypedOp TYPED_MUL = {OP_MUL_INT, OP_MUL_FLOAT, OP_NOTHING, "*"};
|
|
|
-static const TypedOp TYPED_DIV = {OP_DIV_INT, OP_DIV_FLOAT, OP_NOTHING, "/"};
|
|
|
-static const TypedOp TYPED_MOD = {OP_MOD_INT, OP_NOTHING, OP_NOTHING, "%"};
|
|
|
-static const TypedOp TYPED_ADD = {OP_ADD_INT, OP_ADD_FLOAT, OP_NOTHING, "+"};
|
|
|
-static const TypedOp TYPED_SUB = {OP_SUB_INT, OP_SUB_FLOAT, OP_NOTHING, "-"};
|
|
|
-static const TypedOp TYPED_LESS = {OP_LESS_INT, OP_LESS_FLOAT, OP_NOTHING, "<"};
|
|
|
+static const TypedOp TYPED_MUL = {OP_MUL_INT, OP_MUL_FLOAT, OP_NOTHING,
|
|
|
+ OP_NOTHING, "*"};
|
|
|
+static const TypedOp TYPED_DIV = {OP_DIV_INT, OP_DIV_FLOAT, OP_NOTHING,
|
|
|
+ OP_NOTHING, "/"};
|
|
|
+static const TypedOp TYPED_MOD = {OP_MOD_INT, OP_NOTHING, OP_NOTHING,
|
|
|
+ OP_NOTHING, "%"};
|
|
|
+static const TypedOp TYPED_ADD = {OP_ADD_INT, OP_ADD_FLOAT, OP_NOTHING,
|
|
|
+ OP_NOTHING, "+"};
|
|
|
+static const TypedOp TYPED_SUB = {OP_SUB_INT, OP_SUB_FLOAT, OP_NOTHING,
|
|
|
+ OP_NOTHING, "-"};
|
|
|
+static const TypedOp TYPED_LESS = {OP_LESS_INT, OP_LESS_FLOAT, OP_NOTHING,
|
|
|
+ OP_NOTHING, "<"};
|
|
|
static const TypedOp TYPED_LESS_EQUAL = {OP_GREATER_INT, OP_GREATER_FLOAT,
|
|
|
- OP_NOTHING, "<="};
|
|
|
+ OP_NOTHING, OP_NOTHING, "<="};
|
|
|
static const TypedOp TYPED_GREATER = {OP_GREATER_INT, OP_GREATER_FLOAT,
|
|
|
- OP_NOTHING, ">"};
|
|
|
+ OP_NOTHING, OP_NOTHING, ">"};
|
|
|
static const TypedOp TYPED_GREATER_EQUAL = {OP_LESS_INT, OP_LESS_FLOAT,
|
|
|
- OP_NOTHING, ">="};
|
|
|
+ OP_NOTHING, OP_NOTHING, ">="};
|
|
|
static const TypedOp TYPED_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT, OP_EQUAL_BOOL,
|
|
|
- "=="};
|
|
|
+ OP_EQUAL_POINTER, "=="};
|
|
|
static const TypedOp TYPED_NOT_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT,
|
|
|
- OP_EQUAL_BOOL, "!="};
|
|
|
-static const TypedOp TYPED_BIT_OR = {OP_BIT_OR, OP_NOTHING, OP_NOTHING, "|"};
|
|
|
-static const TypedOp TYPED_BIT_XOR = {OP_BIT_XOR, OP_NOTHING, OP_NOTHING, "^"};
|
|
|
-static const TypedOp TYPED_BIT_AND = {OP_BIT_AND, OP_NOTHING, OP_NOTHING, "&"};
|
|
|
+ OP_EQUAL_BOOL, OP_EQUAL_POINTER, "!="};
|
|
|
+static const TypedOp TYPED_BIT_OR = {OP_BIT_OR, OP_NOTHING, OP_NOTHING,
|
|
|
+ OP_NOTHING, "|"};
|
|
|
+static const TypedOp TYPED_BIT_XOR = {OP_BIT_XOR, OP_NOTHING, OP_NOTHING,
|
|
|
+ OP_NOTHING, "^"};
|
|
|
+static const TypedOp TYPED_BIT_AND = {OP_BIT_AND, OP_NOTHING, OP_NOTHING,
|
|
|
+ OP_NOTHING, "&"};
|
|
|
static const TypedOp TYPED_LEFT_SHIFT = {OP_LEFT_SHIFT, OP_NOTHING, OP_NOTHING,
|
|
|
- "<<"};
|
|
|
+ OP_NOTHING, "<<"};
|
|
|
static const TypedOp TYPED_RIGHT_SHIFT = {OP_RIGHT_SHIFT, OP_NOTHING,
|
|
|
- OP_NOTHING, ">>"};
|
|
|
+ OP_NOTHING, OP_NOTHING, ">>"};
|
|
|
|
|
|
static void cError(const char* format, ...) {
|
|
|
va_list args;
|
|
@@ -122,6 +132,16 @@ static void cAddInt(int i) {
|
|
|
bcAddBytes(code, &i, sizeof(int));
|
|
|
}
|
|
|
|
|
|
+static void cAddIntOperation(Operation token, int i) {
|
|
|
+ cAddOperation(token);
|
|
|
+ cAddInt(i);
|
|
|
+}
|
|
|
+
|
|
|
+static void cAddByteOperation(Operation token, char c) {
|
|
|
+ cAddOperation(token);
|
|
|
+ bcAddBytes(code, &c, sizeof(char));
|
|
|
+}
|
|
|
+
|
|
|
static void cAddInt16(int16 i) {
|
|
|
bcAddBytes(code, &i, sizeof(int16));
|
|
|
}
|
|
@@ -155,8 +175,7 @@ static void cConstantInt() {
|
|
|
if(!tReadInt(&value)) {
|
|
|
cError("int token without an int on line %d", line);
|
|
|
}
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(value);
|
|
|
+ cAddIntOperation(OP_PUSH_INT, value);
|
|
|
}
|
|
|
|
|
|
static void cConstantFloat() {
|
|
@@ -192,8 +211,7 @@ static void cCallFunctionArguments(Function* f) {
|
|
|
}
|
|
|
|
|
|
static DataType cCallFunction(const char* name) {
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(0);
|
|
|
+ cAddIntOperation(OP_PUSH_INT, 0);
|
|
|
Function f;
|
|
|
fInit(&f, name, line);
|
|
|
cCallFunctionArguments(&f);
|
|
@@ -216,6 +234,19 @@ static DataType cCallFunction(const char* name) {
|
|
|
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 = cExpression();
|
|
|
+ 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;
|
|
@@ -227,10 +258,8 @@ static void cWalkStruct(Variable* v) {
|
|
|
}
|
|
|
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));
|
|
|
+ cError("%s is not a %s but %s", v->name,
|
|
|
+ pointers ? "struct*" : "struct", cGetName(v->type));
|
|
|
}
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
@@ -243,15 +272,13 @@ static void cWalkStruct(Variable* v) {
|
|
|
offset += inner.address;
|
|
|
}
|
|
|
if(offset > 0) {
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(offset);
|
|
|
- cAddOperation(OP_ADD_INT);
|
|
|
+ cAddIntOperation(OP_PUSH_INT, offset);
|
|
|
+ cAddOperation(OP_ADD_REFERENCE);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static void cReference(Variable* v, int dimension) {
|
|
|
- cAddOperation(OP_DEREFERENCE_VAR);
|
|
|
- cAddInt(v->address);
|
|
|
+ cAddIntOperation(OP_DEREFERENCE_VAR, v->address);
|
|
|
while(dimension > 0) {
|
|
|
if(!dtIsPointer(v->type)) {
|
|
|
cError("too many *");
|
|
@@ -265,7 +292,7 @@ static void cReference(Variable* v, int dimension) {
|
|
|
|
|
|
static void cLoadRef(Variable* v) {
|
|
|
if(dtIsPointer(v->type)) {
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
+ cAddOperation(OP_LOAD_POINTER);
|
|
|
return;
|
|
|
}
|
|
|
switch(v->type.type) {
|
|
@@ -276,8 +303,7 @@ static void cLoadRef(Variable* v) {
|
|
|
if(st == NULL) {
|
|
|
cError("compiler struct error");
|
|
|
}
|
|
|
- cAddOperation(OP_LOAD);
|
|
|
- cAddInt(dtGetSize(v->type, &structs));
|
|
|
+ cAddIntOperation(OP_LOAD, dtGetSize(v->type, &structs));
|
|
|
break;
|
|
|
}
|
|
|
default: cError("cannot load type %s", cGetName(v->type));
|
|
@@ -289,7 +315,7 @@ static void cStore(Variable* v, DataType dt, const char* name) {
|
|
|
cInvalidOperation(v->type, dt, name);
|
|
|
}
|
|
|
if(dtIsPointer(v->type)) {
|
|
|
- cAddOperation(OP_STORE_ARRAY);
|
|
|
+ cAddOperation(OP_STORE_POINTER);
|
|
|
return;
|
|
|
}
|
|
|
switch(v->type.type) {
|
|
@@ -302,14 +328,7 @@ static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
- cReference(v, 0);
|
|
|
- cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(change);
|
|
|
- cAddOperation(OP_ADD_INT);
|
|
|
- cAddOperation(OP_STORE_INT);
|
|
|
+ cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
|
|
|
return dtInt();
|
|
|
}
|
|
|
|
|
@@ -342,15 +361,25 @@ static DataType cBracketPrimary() {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-static DataType cAllocArray(DataType dt, Operation op) {
|
|
|
+static DataType cAllocArray() {
|
|
|
+ cConsumeToken(T_INT);
|
|
|
cConsumeToken(T_OPEN_SQUARE_BRACKET);
|
|
|
DataType index = cExpression();
|
|
|
if(!dtCompare(index, dtInt())) {
|
|
|
cError("array size must be an int");
|
|
|
}
|
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
- cAddOperation(op);
|
|
|
- return dtToArray(dt, 1);
|
|
|
+ cAddIntOperation(OP_NEW, dtGetSize(dtInt(), &structs));
|
|
|
+ return dtToArray(dtInt(), 1);
|
|
|
+}
|
|
|
+
|
|
|
+static DataType cLength() {
|
|
|
+ DataType pointer = cExpression();
|
|
|
+ if(!dtIsPointer(pointer)) {
|
|
|
+ cError("length expects a pointer");
|
|
|
+ }
|
|
|
+ cAddOperation(OP_LENGTH);
|
|
|
+ return dtInt();
|
|
|
}
|
|
|
|
|
|
static DataType cPrimary() {
|
|
@@ -362,7 +391,8 @@ static DataType cPrimary() {
|
|
|
case T_FALSE: cAddOperation(OP_PUSH_FALSE); return dtBool();
|
|
|
case T_OPEN_BRACKET: return cBracketPrimary();
|
|
|
case T_LITERAL: return cLiteral();
|
|
|
- case T_INT: return cAllocArray(dtInt(), OP_INT_ARRAY);
|
|
|
+ case T_NEW: return cAllocArray();
|
|
|
+ case T_LENGTH: return cLength();
|
|
|
default: cUnexpectedToken(t); return dtVoid();
|
|
|
}
|
|
|
}
|
|
@@ -378,14 +408,7 @@ static DataType cPreChange(int change, const char* name) {
|
|
|
if(!dtCompare(v.type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
- cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(change);
|
|
|
- cAddOperation(OP_ADD_INT);
|
|
|
- cAddOperation(OP_STORE_INT);
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
+ cAddByteOperation(OP_PUSH_PRE_INT_CHANGE, change);
|
|
|
return dtInt();
|
|
|
}
|
|
|
|
|
@@ -463,6 +486,9 @@ static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
|
|
|
} else if(dtCompare(a, dtBool()) && dtCompare(b, dtBool()) &&
|
|
|
op->boolOp != OP_NOTHING) {
|
|
|
cAddOperation(op->boolOp);
|
|
|
+ } else if(dtCompare(a, b) && dtIsPointer(a) &&
|
|
|
+ op->pointerOp != OP_NOTHING) {
|
|
|
+ cAddOperation(op->pointerOp);
|
|
|
} else {
|
|
|
cInvalidOperation(a, b, op->name);
|
|
|
}
|
|
@@ -626,12 +652,7 @@ static void cAddPostLineChange(Variable* v, int change, const char* name) {
|
|
|
if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
- cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- cAddOperation(OP_LOAD_INT);
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(change);
|
|
|
- cAddOperation(OP_ADD_INT);
|
|
|
- cAddOperation(OP_STORE_INT);
|
|
|
+ cAddByteOperation(OP_INT_CHANGE, change);
|
|
|
}
|
|
|
|
|
|
static DataType cExtendType(DataType dt) {
|
|
@@ -753,7 +774,7 @@ static void cReturn() {
|
|
|
static void cPrint() {
|
|
|
DataType dt = cExpression();
|
|
|
if(dtIsPointer(dt)) {
|
|
|
- cAddOperation(OP_PRINT_INT);
|
|
|
+ cAddOperation(OP_PRINT_POINTER);
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
return;
|
|
|
}
|
|
@@ -816,8 +837,7 @@ static void cWhile() {
|
|
|
cConsumeScope();
|
|
|
continueAt = oldContinue;
|
|
|
forWhileStack--;
|
|
|
- cAddOperation(OP_GOTO);
|
|
|
- cAddInt(start);
|
|
|
+ cAddIntOperation(OP_GOTO, start);
|
|
|
cSetInt(ifP, code->length);
|
|
|
cConsumeBreaks(breakStart, code->length);
|
|
|
}
|
|
@@ -846,6 +866,14 @@ static void cAddPreLineChange(int change, const char* name) {
|
|
|
cAddPostLineChange(&v, change, name);
|
|
|
}
|
|
|
|
|
|
+static void cDelete() {
|
|
|
+ DataType pointer = cExpression();
|
|
|
+ if(!dtIsPointer(pointer)) {
|
|
|
+ cError("delete expects a pointer");
|
|
|
+ }
|
|
|
+ cAddOperation(OP_DELETE);
|
|
|
+}
|
|
|
+
|
|
|
static void cLineExpression(Token t) {
|
|
|
switch(t) {
|
|
|
case T_LITERAL: cLineLiteral(); break;
|
|
@@ -864,6 +892,7 @@ static void cLineExpression(Token t) {
|
|
|
cLineVariable(cReadString(), c);
|
|
|
break;
|
|
|
}
|
|
|
+ case T_DELETE: cDelete(); break;
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
|
}
|
|
@@ -887,8 +916,7 @@ static void cFor() {
|
|
|
int beginBody = cReserveInt();
|
|
|
int startPerLoop = code->length;
|
|
|
cLineExpression(cReadTokenAndLine());
|
|
|
- cAddOperation(OP_GOTO);
|
|
|
- cAddInt(startCheck);
|
|
|
+ cAddIntOperation(OP_GOTO, startCheck);
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
|
cSetInt(beginBody, code->length);
|
|
|
int breakStart = breakIndex;
|
|
@@ -899,8 +927,7 @@ static void cFor() {
|
|
|
cConsumeBody();
|
|
|
continueAt = oldContinue;
|
|
|
forWhileStack--;
|
|
|
- cAddOperation(OP_GOTO);
|
|
|
- cAddInt(startPerLoop);
|
|
|
+ cAddIntOperation(OP_GOTO, startPerLoop);
|
|
|
cSetInt(end, code->length);
|
|
|
cConsumeBreaks(breakStart, code->length);
|
|
|
|
|
@@ -922,8 +949,7 @@ static void cContinue() {
|
|
|
if(forWhileStack == 0) {
|
|
|
cError("continue without for or while on line %d", line);
|
|
|
}
|
|
|
- cAddOperation(OP_GOTO);
|
|
|
- cAddInt(continueAt);
|
|
|
+ cAddIntOperation(OP_GOTO, continueAt);
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
}
|
|
|
|
|
@@ -1003,8 +1029,7 @@ static int cReserve(int offset) {
|
|
|
}
|
|
|
|
|
|
static void cFree(int p, int bytes) {
|
|
|
- cAddOperation(OP_RETURN);
|
|
|
- cAddInt(bytes);
|
|
|
+ cAddIntOperation(OP_RETURN, bytes);
|
|
|
cSetInt(p, bytes);
|
|
|
}
|
|
|
|
|
@@ -1129,10 +1154,8 @@ static void cCallMain() {
|
|
|
fInit(&f, "main", line);
|
|
|
Function* found = fsSearch(&functions, &f);
|
|
|
if(found != NULL && dtCompare(found->returnType, dtVoid())) {
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
- cAddInt(0);
|
|
|
- cAddOperation(OP_GOSUB);
|
|
|
- cAddInt(found->address);
|
|
|
+ cAddIntOperation(OP_PUSH_INT, 0);
|
|
|
+ cAddIntOperation(OP_GOSUB, found->address);
|
|
|
cAddInt(found->size);
|
|
|
}
|
|
|
}
|