|
@@ -18,13 +18,11 @@ static int16 line = 1;
|
|
|
|
|
|
static jmp_buf errorJump;
|
|
|
|
|
|
-
|
|
|
+#define RETURN_BUFFER 16
|
|
|
#define BREAK_BUFFER 32
|
|
|
|
|
|
#define DT_OPERATION(op) \
|
|
|
- case DT_INT32: cAddOperation(OP_##op##_INT32); break; \
|
|
|
- case DT_INT64: cAddOperation(OP_##op##_INT64); break; \
|
|
|
- case DT_BOOL: cAddOperation(OP_##op##_BOOL); break; \
|
|
|
+ case DT_INT: cAddOperation(OP_##op##_INT); break; \
|
|
|
case DT_FLOAT: cAddOperation(OP_##op##_FLOAT); break;
|
|
|
|
|
|
typedef DataType (*Parser)(void);
|
|
@@ -49,33 +47,30 @@ static int continueAt = 0;
|
|
|
|
|
|
typedef struct {
|
|
|
Operation intOp;
|
|
|
- Operation longOp;
|
|
|
Operation floatOp;
|
|
|
- Operation boolOp;
|
|
|
Operation pointerOp;
|
|
|
const char* name;
|
|
|
} TypedOp;
|
|
|
|
|
|
-#define TYPE_OP(NAME, FLOAT, BOOL, POINTER, text) \
|
|
|
- static const TypedOp TYPED_##NAME = {OP_##NAME##_INT32, OP_##NAME##_INT64, \
|
|
|
- OP_##FLOAT, OP_##BOOL, \
|
|
|
- OP_##POINTER, text};
|
|
|
-TYPE_OP(MUL, MUL_FLOAT, NOTHING, NOTHING, "*")
|
|
|
-TYPE_OP(DIV, DIV_FLOAT, NOTHING, NOTHING, "/")
|
|
|
-TYPE_OP(MOD, NOTHING, NOTHING, NOTHING, "%")
|
|
|
-TYPE_OP(ADD, ADD_FLOAT, NOTHING, NOTHING, "+")
|
|
|
-TYPE_OP(SUB, SUB_FLOAT, NOTHING, NOTHING, "-")
|
|
|
-TYPE_OP(LESS, LESS_FLOAT, NOTHING, NOTHING, "<")
|
|
|
-TYPE_OP(LESS_EQUAL, LESS_EQUAL_FLOAT, NOTHING, NOTHING, "<=")
|
|
|
-TYPE_OP(GREATER, GREATER_FLOAT, NOTHING, NOTHING, ">")
|
|
|
-TYPE_OP(GREATER_EQUAL, GREATER_EQUAL_FLOAT, NOTHING, NOTHING, ">=")
|
|
|
-TYPE_OP(EQUAL, EQUAL_FLOAT, EQUAL_BOOL, EQUAL_POINTER, "==")
|
|
|
-TYPE_OP(NOT_EQUAL, NOT_EQUAL_FLOAT, NOT_EQUAL_BOOL, NOT_EQUAL_POINTER, "!=")
|
|
|
-TYPE_OP(BIT_OR, NOTHING, NOTHING, NOTHING, "|")
|
|
|
-TYPE_OP(BIT_XOR, NOTHING, NOTHING, NOTHING, "^")
|
|
|
-TYPE_OP(BIT_AND, NOTHING, NOTHING, NOTHING, "&")
|
|
|
-TYPE_OP(LEFT_SHIFT, NOTHING, NOTHING, NOTHING, "<<")
|
|
|
-TYPE_OP(RIGHT_SHIFT, NOTHING, NOTHING, NOTHING, ">>")
|
|
|
+#define TYPE_OP(NAME, FLOAT, POINTER, text) \
|
|
|
+ static const TypedOp TYPED_##NAME = {OP_##NAME##_INT, OP_##FLOAT, \
|
|
|
+ OP_##POINTER, text};
|
|
|
+TYPE_OP(MUL, MUL_FLOAT, NOTHING, "*")
|
|
|
+TYPE_OP(DIV, DIV_FLOAT, NOTHING, "/")
|
|
|
+TYPE_OP(MOD, NOTHING, NOTHING, "%")
|
|
|
+TYPE_OP(ADD, ADD_FLOAT, NOTHING, "+")
|
|
|
+TYPE_OP(SUB, SUB_FLOAT, NOTHING, "-")
|
|
|
+TYPE_OP(LESS, LESS_FLOAT, NOTHING, "<")
|
|
|
+TYPE_OP(LESS_EQUAL, LESS_EQUAL_FLOAT, NOTHING, "<=")
|
|
|
+TYPE_OP(GREATER, GREATER_FLOAT, NOTHING, ">")
|
|
|
+TYPE_OP(GREATER_EQUAL, GREATER_EQUAL_FLOAT, NOTHING, ">=")
|
|
|
+TYPE_OP(EQUAL, EQUAL_FLOAT, EQUAL_POINTER, "==")
|
|
|
+TYPE_OP(NOT_EQUAL, NOT_EQUAL_FLOAT, NOT_EQUAL_POINTER, "!=")
|
|
|
+TYPE_OP(BIT_OR, NOTHING, NOTHING, "|")
|
|
|
+TYPE_OP(BIT_XOR, NOTHING, NOTHING, "^")
|
|
|
+TYPE_OP(BIT_AND, NOTHING, NOTHING, "&")
|
|
|
+TYPE_OP(LEFT_SHIFT, NOTHING, NOTHING, "<<")
|
|
|
+TYPE_OP(RIGHT_SHIFT, NOTHING, NOTHING, ">>")
|
|
|
|
|
|
static void cError(const char* format, ...) {
|
|
|
va_list args;
|
|
@@ -109,6 +104,19 @@ static void cUnexpectedToken(Token t) {
|
|
|
cError("unexpected token: %s", tGetName(t));
|
|
|
}
|
|
|
|
|
|
+#define BUFFER_SIZE 256
|
|
|
+
|
|
|
+static void cUnknownFunction(Function* f) {
|
|
|
+ int max = 0;
|
|
|
+ char buffer[BUFFER_SIZE] = {'\0'};
|
|
|
+ for(int i = 0; i < f->arguments; i++) {
|
|
|
+ const char* name = dtGetName(&structs, f->argumentTypes[i]);
|
|
|
+ max += snprintf(buffer + max, BUFFER_SIZE - max, i > 0 ? ", %s" : "%s",
|
|
|
+ name);
|
|
|
+ }
|
|
|
+ cError("unknown function: %s(%s)", f->name, buffer);
|
|
|
+}
|
|
|
+
|
|
|
static void cAddOperation(Operation token) {
|
|
|
unsigned char c = token;
|
|
|
bcAddBytes(code, &c, 1);
|
|
@@ -126,10 +134,6 @@ static void cAddInt32(int32 i) {
|
|
|
bcAddBytes(code, &i, sizeof(int32));
|
|
|
}
|
|
|
|
|
|
-static void cAddInt64(int64 i) {
|
|
|
- bcAddBytes(code, &i, sizeof(int64));
|
|
|
-}
|
|
|
-
|
|
|
static void cAddInt32Operation(Operation token, int32 i) {
|
|
|
cAddOperation(token);
|
|
|
cAddInt32(i);
|
|
@@ -140,18 +144,18 @@ static void cAddByteOperation(Operation token, int8 i) {
|
|
|
bcAddBytes(code, &i, sizeof(int8));
|
|
|
}
|
|
|
|
|
|
-static void cAddLine(int16 i) {
|
|
|
+static void cAddLine(int16 line) {
|
|
|
cAddOperation(OP_LINE);
|
|
|
- bcAddBytes(code, &i, sizeof(int16));
|
|
|
+ bcAddBytes(code, &line, sizeof(int16));
|
|
|
}
|
|
|
|
|
|
static Token cReadTokenAndLine() {
|
|
|
-
|
|
|
- Token t = tReadToken();
|
|
|
- if(tReadInt16(&line)) {
|
|
|
- return t;
|
|
|
+ hasReturn--;
|
|
|
+ Token t;
|
|
|
+ if(tReadTokenAndLine(&t, &line)) {
|
|
|
+ return T_END;
|
|
|
}
|
|
|
- return T_END;
|
|
|
+ return t;
|
|
|
}
|
|
|
|
|
|
static void cConsumeToken(Token wanted) {
|
|
@@ -167,24 +171,15 @@ static bool cConsumeTokenIf(Token t) {
|
|
|
|
|
|
static void cConstantInt32() {
|
|
|
int32 value;
|
|
|
- if(!tReadInt32(&value)) {
|
|
|
+ if(tReadInt32(&value)) {
|
|
|
cError("int token without an int");
|
|
|
}
|
|
|
- cAddInt32Operation(OP_PUSH_INT32, value);
|
|
|
-}
|
|
|
-
|
|
|
-static void cConstantInt64() {
|
|
|
- int64 value;
|
|
|
- if(!tReadInt64(&value)) {
|
|
|
- cError("long token without an long");
|
|
|
- }
|
|
|
- cAddOperation(OP_PUSH_INT64);
|
|
|
- cAddInt64(value);
|
|
|
+ cAddInt32Operation(OP_PUSH_INT, value);
|
|
|
}
|
|
|
|
|
|
static void cConstantFloat() {
|
|
|
float value;
|
|
|
- if(!tReadFloat(&value)) {
|
|
|
+ if(tReadFloat(&value)) {
|
|
|
cError("float token without a float");
|
|
|
}
|
|
|
cAddOperation(OP_PUSH_FLOAT);
|
|
@@ -203,33 +198,18 @@ static int cGetSize(DataType dt) {
|
|
|
return dtGetSize(dt, &structs);
|
|
|
}
|
|
|
|
|
|
-static DataType cDereference(DataType dt) {
|
|
|
- if(dtDereference(&dt)) {
|
|
|
- cError("%s dereferenced too often", cGetName(dt));
|
|
|
- }
|
|
|
- return dt;
|
|
|
-}
|
|
|
-
|
|
|
-static DataType cExtendType(DataType dt, bool constant) {
|
|
|
- while(cConsumeTokenIf(T_MUL)) {
|
|
|
- dt = cDereference(dt);
|
|
|
- }
|
|
|
- if(constant) {
|
|
|
- dt = dtConst(dt);
|
|
|
+static DataType cExtendType(DataType dt) {
|
|
|
+ if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
|
|
|
+ cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
+ dt = dtToArray(dt);
|
|
|
}
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
static DataType cReadType(Token t, bool force) {
|
|
|
- bool c = t == T_CONST;
|
|
|
- if(c) {
|
|
|
- t = cReadTokenAndLine();
|
|
|
- }
|
|
|
switch(t) {
|
|
|
- case T_INT32: return cExtendType(dtInt32(), c);
|
|
|
- case T_INT64: return cExtendType(dtInt64(), c);
|
|
|
- case T_BOOL: return cExtendType(dtBool(), c);
|
|
|
- case T_FLOAT: return cExtendType(dtFloat(), c);
|
|
|
+ case T_INT: return dtInt();
|
|
|
+ case T_FLOAT: return dtFloat();
|
|
|
case T_LITERAL: {
|
|
|
Struct* st = stsSearch(&structs, cReadString());
|
|
|
if(st == NULL) {
|
|
@@ -239,7 +219,7 @@ static DataType cReadType(Token t, bool force) {
|
|
|
return dtVoid();
|
|
|
}
|
|
|
}
|
|
|
- return cExtendType(dtStruct(st), c);
|
|
|
+ return dtStruct(st);
|
|
|
}
|
|
|
default:
|
|
|
if(force) {
|
|
@@ -249,22 +229,29 @@ static DataType cReadType(Token t, bool force) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static DataType cReadExtendedType(Token t, bool force) {
|
|
|
+ DataType dt = cReadType(t, force);
|
|
|
+ if(!dtIsVoid(dt)) {
|
|
|
+ dt = cExtendType(dt);
|
|
|
+ }
|
|
|
+ return dt;
|
|
|
+}
|
|
|
+
|
|
|
static DataType cExpression();
|
|
|
|
|
|
static void cLoadRef(DataType type) {
|
|
|
- if(dtIsPointer(type)) {
|
|
|
- cAddOperation(OP_REFERENCE);
|
|
|
+ if(dtIsArray(type)) {
|
|
|
+ cAddOperation(OP_LOAD_ARRAY);
|
|
|
return;
|
|
|
}
|
|
|
switch(type.type) {
|
|
|
DT_OPERATION(LOAD);
|
|
|
- case DT_STRUCT: cAddInt32Operation(OP_LOAD, cGetSize(type)); break;
|
|
|
default: cError("cannot load type %s", cGetName(type));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static DataType cUnpack(DataType dt) {
|
|
|
- if(dtRemoveVariable(&dt)) {
|
|
|
+ if(dt.type != DT_STRUCT && dtRemovePointer(&dt)) {
|
|
|
cLoadRef(dt);
|
|
|
}
|
|
|
return dt;
|
|
@@ -297,14 +284,14 @@ static DataType cCallFunction(const char* name) {
|
|
|
onLine = false;
|
|
|
cCallFunctionArguments(&f);
|
|
|
onLine = oldOnLine;
|
|
|
- Function* found = fsSearch(&functions, &f, false);
|
|
|
+ Function* found = fsSearch(&functions, &f);
|
|
|
if(found == NULL) {
|
|
|
- cError("unknown function");
|
|
|
+ cUnknownFunction(&f);
|
|
|
} else if(found->global) {
|
|
|
cAddInt32Operation(OP_CALL, found->line);
|
|
|
return found->returnType;
|
|
|
}
|
|
|
- char push[1 + sizeof(int32)] = {OP_PUSH_INT32};
|
|
|
+ char push[1 + sizeof(int32)] = {OP_PUSH_INT};
|
|
|
bcInsertBytes(code, push, sizeof(push), returnAddress);
|
|
|
cAddOperation(OP_GOSUB);
|
|
|
if(found->address == -1) {
|
|
@@ -319,15 +306,14 @@ static DataType cCallFunction(const char* name) {
|
|
|
}
|
|
|
|
|
|
static void cStore(DataType left, DataType right, const char* name) {
|
|
|
- if(dtIsPointer(left)) {
|
|
|
- if(!dtNullCompare(left, right) &&
|
|
|
- !dtNullCompare(left, dtConst(right))) {
|
|
|
+ if(dtIsArray(left)) {
|
|
|
+ if(!dtCompare(left, right)) {
|
|
|
cInvalidOperation(left, right, name);
|
|
|
}
|
|
|
- cAddOperation(OP_STORE_POINTER);
|
|
|
+ cAddOperation(OP_STORE_ARRAY);
|
|
|
return;
|
|
|
}
|
|
|
- if(!dtNullCompare(left, right) && !dtNullCompare(dtConst(left), right)) {
|
|
|
+ if(!dtCompare(left, right)) {
|
|
|
cInvalidOperation(left, right, name);
|
|
|
}
|
|
|
switch(left.type) {
|
|
@@ -343,11 +329,19 @@ static DataType cLiteral() {
|
|
|
}
|
|
|
Variable v;
|
|
|
if(!vsSearch(&vars, &v, literal)) {
|
|
|
- cAddInt32Operation(OP_DEREFERENCE_VAR, v.address);
|
|
|
- return dtToVariable(v.type);
|
|
|
+ if(v.type.pointer != 0) {
|
|
|
+ if(v.type.type != DT_STRUCT) {
|
|
|
+ cError("non struct type %s should not be a pointer here",
|
|
|
+ cGetName(v.type));
|
|
|
+ }
|
|
|
+ cAddInt32Operation(OP_PUSH_STRUCT_REFERENCE, v.address);
|
|
|
+ } else {
|
|
|
+ cAddInt32Operation(OP_DEREFERENCE_VAR, v.address);
|
|
|
+ }
|
|
|
+ return dtToPointer(v.type);
|
|
|
} else if(!vsSearch(&globalVars, &v, literal)) {
|
|
|
cAddInt32Operation(OP_DEREFERENCE_GVAR, v.address);
|
|
|
- return dtToVariable(v.type);
|
|
|
+ return dtToPointer(v.type);
|
|
|
}
|
|
|
cNotDeclared(literal);
|
|
|
return dtVoid();
|
|
@@ -358,12 +352,12 @@ static DataType cText() {
|
|
|
int32 lengthAddress = cReserveInt32();
|
|
|
int32 length = 0;
|
|
|
int32 c;
|
|
|
- while(tReadInt32(&c) && c != 0) {
|
|
|
+ while(!tReadInt32(&c) && c != 0) {
|
|
|
cAddInt32(c);
|
|
|
length++;
|
|
|
}
|
|
|
cSetInt32(lengthAddress, length);
|
|
|
- return dtConst(dtText());
|
|
|
+ return dtText();
|
|
|
}
|
|
|
|
|
|
static DataType cBracketPrimary() {
|
|
@@ -372,39 +366,38 @@ static DataType cBracketPrimary() {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-static void cArrayIndex(const char* name) {
|
|
|
- if(!dtIsInt32(cUnpackedExpression())) {
|
|
|
- cError("array %s must be an int", name);
|
|
|
+static void cArrayIndex() {
|
|
|
+ if(!dtIsInt(cUnpackedExpression())) {
|
|
|
+ cError("array index must be an int");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static DataType cAllocArray() {
|
|
|
DataType dt = cReadType(cReadTokenAndLine(), true);
|
|
|
+ if(dt.array != 0) {
|
|
|
+ cError("array type must not be an array");
|
|
|
+ }
|
|
|
cConsumeToken(T_OPEN_SQUARE_BRACKET);
|
|
|
- cArrayIndex("size");
|
|
|
+ cArrayIndex();
|
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
cAddInt32Operation(OP_NEW, cGetSize(dt));
|
|
|
- return cDereference(dt);
|
|
|
+ return dtToArray(dt);
|
|
|
}
|
|
|
|
|
|
static DataType cLength() {
|
|
|
- DataType pointer = cUnpackedExpression();
|
|
|
- if(!dtIsPointer(pointer)) {
|
|
|
- cError("length expects a pointer");
|
|
|
+ DataType array = cUnpackedExpression();
|
|
|
+ if(!dtIsArray(array)) {
|
|
|
+ cError("length expects an array");
|
|
|
}
|
|
|
cAddOperation(OP_LENGTH);
|
|
|
- return dtInt32();
|
|
|
+ return dtInt();
|
|
|
}
|
|
|
|
|
|
static DataType cPrimary() {
|
|
|
Token t = cReadTokenAndLine();
|
|
|
switch(t) {
|
|
|
- case T_CONST_INT32: cConstantInt32(); return dtInt32();
|
|
|
- case T_CONST_INT64: cConstantInt64(); return dtInt64();
|
|
|
- case T_CONST_FLOAT: cConstantFloat(); return dtFloat();
|
|
|
- case T_TRUE: cAddOperation(OP_PUSH_TRUE); return dtBool();
|
|
|
- case T_FALSE: cAddOperation(OP_PUSH_FALSE); return dtBool();
|
|
|
- case T_NULLPTR: cAddOperation(OP_PUSH_NULLPTR); return dtNull();
|
|
|
+ case T_INT_VALUE: cConstantInt32(); return dtInt();
|
|
|
+ case T_FLOAT_VALUE: cConstantFloat(); return dtFloat();
|
|
|
case T_TEXT: return cText();
|
|
|
case T_OPEN_BRACKET: return cBracketPrimary();
|
|
|
case T_LITERAL: return cLiteral();
|
|
@@ -415,7 +408,7 @@ static DataType cPrimary() {
|
|
|
}
|
|
|
|
|
|
static void cRemoveReference(DataType* dt, const char* name) {
|
|
|
- if(!dtRemoveVariable(dt)) {
|
|
|
+ if(!dtRemovePointer(dt)) {
|
|
|
cError("%s needs a reference not %s", name, cGetName(*dt));
|
|
|
}
|
|
|
}
|
|
@@ -438,19 +431,17 @@ static void cChangeType(DataType* dt, Operation op, Operation pushOp,
|
|
|
|
|
|
static void cPostChange(DataType* dt, int change, const char* name) {
|
|
|
cRemoveReference(dt, name);
|
|
|
- if(dtIsInt32(*dt)) {
|
|
|
- cChangeType(dt, OP_CHANGE_INT32, OP_PUSH_POST_CHANGE_INT32, change);
|
|
|
- } else if(dtIsInt64(*dt)) {
|
|
|
- cChangeType(dt, OP_CHANGE_INT64, OP_PUSH_POST_CHANGE_INT64, change);
|
|
|
+ if(dtIsInt(*dt)) {
|
|
|
+ cChangeType(dt, OP_CHANGE_INT, OP_PUSH_POST_CHANGE_INT, change);
|
|
|
} else {
|
|
|
- cError("%s needs an int or long not %s", name, cGetName(*dt));
|
|
|
+ cError("%s needs an int not %s", name, cGetName(*dt));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static DataType cStructAccess(DataType dt, int pointers) {
|
|
|
+static DataType cStructAccess(DataType dt) {
|
|
|
Struct* st = dtGetStruct(&structs, dt);
|
|
|
- if(st == NULL || dt.pointers != pointers) {
|
|
|
- cError(pointers == 0 ? ". expects a struct" : "-> expects a struct*");
|
|
|
+ if(st == NULL) {
|
|
|
+ cError(". expects a struct not %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
@@ -458,12 +449,10 @@ static DataType cStructAccess(DataType dt, int pointers) {
|
|
|
if(vSearchStruct(&inner, &structs, st, name)) {
|
|
|
cError("%s has no member %s", st->name, name);
|
|
|
} else if(inner.address > 0) {
|
|
|
- cAddInt32Operation(OP_PUSH_INT32, inner.address);
|
|
|
+ cAddInt32Operation(OP_PUSH_INT, inner.address);
|
|
|
cAddInt32Operation(OP_ADD_REFERENCE, 1);
|
|
|
}
|
|
|
- DataType r = dtToVariable(inner.type);
|
|
|
- r.constant = dt.constant;
|
|
|
- return r;
|
|
|
+ return dtToPointer(inner.type);
|
|
|
}
|
|
|
|
|
|
static DataType cAccess() {
|
|
@@ -475,19 +464,17 @@ static DataType cAccess() {
|
|
|
cPostChange(&dt, -1, "--");
|
|
|
} else if(cConsumeTokenIf(T_POINT)) {
|
|
|
cRemoveReference(&dt, ".");
|
|
|
- dt = cStructAccess(dt, 0);
|
|
|
- } else if(cConsumeTokenIf(T_ARROW)) {
|
|
|
- dt = cStructAccess(cUnpack(dt), 1);
|
|
|
+ dt = cStructAccess(dt);
|
|
|
} else if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
|
|
|
- dt = cUnpack(dt);
|
|
|
- if(!dtIsPointer(dt)) {
|
|
|
- cError("[] needs a pointer");
|
|
|
+ if(!dtIsArray(dt)) {
|
|
|
+ cError("[] needs an array");
|
|
|
}
|
|
|
+ cAddOperation(OP_LOAD_ARRAY);
|
|
|
+ dtRemovePointer(&dt);
|
|
|
cArrayIndex("index");
|
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
- dt = dtReference(dt);
|
|
|
cAddInt32Operation(OP_ADD_REFERENCE, cGetSize(dt));
|
|
|
- dt = dtToVariable(dt);
|
|
|
+ dt = dtToPointer(dtRemoveArray(dt));
|
|
|
} else {
|
|
|
return dt;
|
|
|
}
|
|
@@ -496,21 +483,17 @@ static DataType cAccess() {
|
|
|
|
|
|
static DataType cPreChange(DataType dt, int change, const char* name) {
|
|
|
cRemoveReference(&dt, name);
|
|
|
- if(dtIsInt32(dt)) {
|
|
|
- cChangeType(&dt, OP_CHANGE_INT32, OP_PUSH_PRE_CHANGE_INT32, change);
|
|
|
- } else if(dtIsInt64(dt)) {
|
|
|
- cChangeType(&dt, OP_CHANGE_INT64, OP_PUSH_PRE_CHANGE_INT64, change);
|
|
|
+ if(dtIsInt(dt)) {
|
|
|
+ cChangeType(&dt, OP_CHANGE_INT, OP_PUSH_PRE_CHANGE_INT, change);
|
|
|
} else {
|
|
|
- cError("%s needs an int or long not %s", name, cGetName(dt));
|
|
|
+ cError("%s needs an int not %s", name, cGetName(dt));
|
|
|
}
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
static DataType cInvertSign(DataType dt) {
|
|
|
- if(dtIsInt32(dt)) {
|
|
|
- cAddOperation(OP_INVERT_SIGN_INT32);
|
|
|
- } else if(dtIsInt64(dt)) {
|
|
|
- cAddOperation(OP_INVERT_SIGN_INT64);
|
|
|
+ if(dtIsInt(dt)) {
|
|
|
+ cAddOperation(OP_INVERT_SIGN_INT);
|
|
|
} else if(dtIsFloat(dt)) {
|
|
|
cAddOperation(OP_INVERT_SIGN_FLOAT);
|
|
|
} else {
|
|
@@ -519,12 +502,9 @@ static DataType cInvertSign(DataType dt) {
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
-static DataType cCast(DataType in, DataType a, Operation aOp, DataType b,
|
|
|
- Operation bOp, DataType out) {
|
|
|
+static DataType cCast(DataType in, DataType a, Operation aOp, DataType out) {
|
|
|
if(dtCompare(in, a)) {
|
|
|
cAddOperation(aOp);
|
|
|
- } else if(dtCompare(in, b)) {
|
|
|
- cAddOperation(bOp);
|
|
|
} else {
|
|
|
cError("cannot cast %s to %s", cGetName(in), cGetName(out));
|
|
|
}
|
|
@@ -532,36 +512,16 @@ static DataType cCast(DataType in, DataType a, Operation aOp, DataType b,
|
|
|
}
|
|
|
|
|
|
static DataType cUnaryNot(DataType dt) {
|
|
|
- cExpectType(dt, dtBool(), "!");
|
|
|
+ cExpectType(dt, dtInt(), "!");
|
|
|
cAddOperation(OP_NOT);
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
static DataType cUnaryBitNot(DataType dt) {
|
|
|
- if(dtIsInt32(dt)) {
|
|
|
- cAddOperation(OP_BIT_NOT_INT32);
|
|
|
- } else if(dtIsInt64(dt)) {
|
|
|
- cAddOperation(OP_BIT_NOT_INT64);
|
|
|
+ if(dtIsInt(dt)) {
|
|
|
+ cAddOperation(OP_BIT_NOT_INT);
|
|
|
} else {
|
|
|
- cError("~ needs an int or long not %s", cGetName(dt));
|
|
|
- }
|
|
|
- return dt;
|
|
|
-}
|
|
|
-
|
|
|
-static DataType cUnaryDereference(DataType dt) {
|
|
|
- cRemoveReference(&dt, "&");
|
|
|
- return cDereference(dt);
|
|
|
-}
|
|
|
-
|
|
|
-static DataType cUnaryReference(DataType dt) {
|
|
|
- if(!dtIsPointer(dt)) {
|
|
|
- cError("* expects a pointer");
|
|
|
- }
|
|
|
- dt = dtReference(dt);
|
|
|
- if(!dtIsPointer(dt) && !dtIsVariable(dt)) {
|
|
|
- dt = dtToVariable(dt);
|
|
|
- } else {
|
|
|
- cAddOperation(OP_REFERENCE);
|
|
|
+ cError("~ needs an int not %s", cGetName(dt));
|
|
|
}
|
|
|
return dt;
|
|
|
}
|
|
@@ -570,16 +530,11 @@ static DataType cPreUnary() {
|
|
|
int marker = tGetMarker();
|
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
if(cConsumeTokenIf(T_FLOAT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
- return cCast(cUnpack(cPreUnary()), dtInt32(), OP_INT32_TO_FLOAT,
|
|
|
- dtInt64(), OP_INT64_TO_FLOAT, dtFloat());
|
|
|
- } else if(cConsumeTokenIf(T_INT32) &&
|
|
|
- cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
- return cCast(cUnpack(cPreUnary()), dtFloat(), OP_FLOAT_TO_INT32,
|
|
|
- dtInt64(), OP_INT64_TO_INT32, dtInt32());
|
|
|
- } else if(cConsumeTokenIf(T_INT64) &&
|
|
|
- cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
- return cCast(cUnpack(cPreUnary()), dtInt32(), OP_INT32_TO_INT64,
|
|
|
- dtFloat(), OP_FLOAT_TO_INT64, dtInt64());
|
|
|
+ return cCast(cUnpack(cPreUnary()), dtInt(), OP_INT_TO_FLOAT,
|
|
|
+ dtFloat());
|
|
|
+ } else if(cConsumeTokenIf(T_INT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
+ return cCast(cUnpack(cPreUnary()), dtFloat(), OP_FLOAT_TO_INT,
|
|
|
+ dtInt());
|
|
|
}
|
|
|
}
|
|
|
tReset(marker);
|
|
@@ -593,10 +548,6 @@ static DataType cPreUnary() {
|
|
|
return cUnaryNot(cPreUnary());
|
|
|
} else if(cConsumeTokenIf(T_BIT_NOT)) {
|
|
|
return cUnaryBitNot(cPreUnary());
|
|
|
- } else if(cConsumeTokenIf(T_BIT_AND)) {
|
|
|
- return cUnaryDereference(cPreUnary());
|
|
|
- } else if(cConsumeTokenIf(T_MUL)) {
|
|
|
- return cUnaryReference(cPreUnary());
|
|
|
}
|
|
|
return cAccess();
|
|
|
}
|
|
@@ -604,19 +555,13 @@ static DataType cPreUnary() {
|
|
|
static void cAddTypeOperation(DataType* a, Parser bf, const TypedOp* op) {
|
|
|
*a = cUnpack(*a);
|
|
|
DataType b = cUnpack(bf());
|
|
|
- a->constant = 0;
|
|
|
- b.constant = 0;
|
|
|
- if(!dtNullCompare(*a, b)) {
|
|
|
+ if(!dtCompare(*a, b)) {
|
|
|
cInvalidOperation(*a, b, op->name);
|
|
|
- } else if(dtIsInt32(*a) && op->intOp != OP_NOTHING) {
|
|
|
+ } else if(dtIsInt(*a) && op->intOp != OP_NOTHING) {
|
|
|
cAddOperation(op->intOp);
|
|
|
- } else if(dtIsInt64(*a) && op->longOp != OP_NOTHING) {
|
|
|
- cAddOperation(op->longOp);
|
|
|
} else if(dtIsFloat(*a) && op->floatOp != OP_NOTHING) {
|
|
|
cAddOperation(op->floatOp);
|
|
|
- } else if(dtIsBool(*a) && op->boolOp != OP_NOTHING) {
|
|
|
- cAddOperation(op->boolOp);
|
|
|
- } else if(dtIsPointer(*a) && op->pointerOp != OP_NOTHING) {
|
|
|
+ } else if(dtIsArray(*a) && op->pointerOp != OP_NOTHING) {
|
|
|
cAddOperation(op->pointerOp);
|
|
|
} else {
|
|
|
cInvalidOperation(*a, b, op->name);
|
|
@@ -669,16 +614,16 @@ static DataType cComparison() {
|
|
|
while(true) {
|
|
|
if(cConsumeTokenIf(T_LESS)) {
|
|
|
cAddTypeOperation(&a, cShift, &TYPED_LESS);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else if(cConsumeTokenIf(T_LESS_EQUAL)) {
|
|
|
cAddTypeOperation(&a, cShift, &TYPED_LESS_EQUAL);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else if(cConsumeTokenIf(T_GREATER)) {
|
|
|
cAddTypeOperation(&a, cShift, &TYPED_GREATER);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
|
|
|
cAddTypeOperation(&a, cShift, &TYPED_GREATER_EQUAL);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else {
|
|
|
return a;
|
|
|
}
|
|
@@ -690,10 +635,10 @@ static DataType cEqual() {
|
|
|
while(true) {
|
|
|
if(cConsumeTokenIf(T_EQUAL)) {
|
|
|
cAddTypeOperation(&a, cComparison, &TYPED_EQUAL);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else if(cConsumeTokenIf(T_NOT_EQUAL)) {
|
|
|
cAddTypeOperation(&a, cComparison, &TYPED_NOT_EQUAL);
|
|
|
- a = dtBool();
|
|
|
+ a = dtInt();
|
|
|
} else {
|
|
|
return a;
|
|
|
}
|
|
@@ -723,11 +668,10 @@ static DataType cBitOr() {
|
|
|
static DataType cLogical(Parser f, Token t, Operation jump, Operation op) {
|
|
|
DataType a = f();
|
|
|
while(cConsumeTokenIf(t)) {
|
|
|
- a = cUnpack(a);
|
|
|
cAddOperation(jump);
|
|
|
int32 p = cReserveInt32();
|
|
|
- DataType b = cUnpack(f());
|
|
|
- if(!dtIsBool(a) || !dtIsBool(b)) {
|
|
|
+ DataType b = f();
|
|
|
+ if(!dtIsInt(a) || !dtIsInt(b)) {
|
|
|
cInvalidOperation(a, b, tGetName(t));
|
|
|
}
|
|
|
cAddOperation(op);
|
|
@@ -780,18 +724,13 @@ static void cReturn() {
|
|
|
return;
|
|
|
}
|
|
|
DataType dt = cUnpackedExpression();
|
|
|
- if(!dtNullCompare(returnType, dt) &&
|
|
|
- !dtNullCompare(returnType, dtConst(dt))) {
|
|
|
+ if(!dtCompare(returnType, dt)) {
|
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
|
- } else if(dtIsInt32(dt)) {
|
|
|
- cAddReturn(OP_RETURN_INT32);
|
|
|
- } else if(dtIsInt64(dt)) {
|
|
|
- cAddReturn(OP_RETURN_INT64);
|
|
|
- } else if(dtIsBool(dt)) {
|
|
|
- cAddReturn(OP_RETURN_BOOL);
|
|
|
+ } else if(dtIsInt(dt)) {
|
|
|
+ cAddReturn(OP_RETURN_INT);
|
|
|
} else if(dtIsFloat(dt)) {
|
|
|
cAddReturn(OP_RETURN_FLOAT);
|
|
|
- } else if(dtIsPointer(dt) || dtIsNull(dt)) {
|
|
|
+ } else if(dtIsArray(dt)) {
|
|
|
cAddReturn(OP_RETURN_POINTER);
|
|
|
} else {
|
|
|
cError("cannot return %s", cGetName(dt));
|
|
@@ -802,7 +741,7 @@ static void cReturn() {
|
|
|
|
|
|
static void cIf() {
|
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
|
- cExpectType(cUnpackedExpression(), dtBool(), "if");
|
|
|
+ cExpectType(cExpression(), dtInt(), "if");
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
|
cAddOperation(OP_IF_GOTO);
|
|
|
int32 ifP = cReserveInt32();
|
|
@@ -833,7 +772,7 @@ static void cConsumeBreaks(int start, int address) {
|
|
|
static void cWhile() {
|
|
|
int start = code->length;
|
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
|
- cExpectType(cUnpackedExpression(), dtBool(), "while");
|
|
|
+ cExpectType(cExpression(), dtInt(), "while");
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
|
cAddOperation(OP_IF_GOTO);
|
|
|
int32 ifP = cReserveInt32();
|
|
@@ -850,19 +789,8 @@ static void cWhile() {
|
|
|
cConsumeBreaks(breakStart, code->length);
|
|
|
}
|
|
|
|
|
|
-static void cDelete() {
|
|
|
- DataType pointer = cUnpackedExpression();
|
|
|
- if(!dtIsPointer(pointer) || pointer.constant) {
|
|
|
- cError("delete expects a non const pointer");
|
|
|
- }
|
|
|
- cAddOperation(OP_DELETE);
|
|
|
-}
|
|
|
-
|
|
|
static void cOperationSet(DataType left, const TypedOp* op) {
|
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
- if(left.constant) {
|
|
|
- cError("cannot use %s= on const reference", op->name);
|
|
|
- }
|
|
|
cLoadRef(left);
|
|
|
cAddTypeOperation(&left, cUnpackedExpression, op);
|
|
|
cStore(left, left, "=");
|
|
@@ -899,19 +827,16 @@ static void cDeclareSet(Variables* vs, DataType dt, const char* var,
|
|
|
cDeclared(var);
|
|
|
}
|
|
|
Variable* v = vsAdd(vs, var, dt, &structs);
|
|
|
- if(dt.type != DT_STRUCT || dtIsPointer(dt)) {
|
|
|
+ if(dt.type != DT_STRUCT || dtIsArray(dt)) {
|
|
|
cConsumeToken(T_SET);
|
|
|
cAddInt32Operation(op, v->address);
|
|
|
DataType right = cUnpackedExpression();
|
|
|
- if(!right.constant) {
|
|
|
- dt.constant = 0;
|
|
|
- }
|
|
|
cStore(dt, right, "=");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static bool cDeclaration(Token t) {
|
|
|
- DataType dt = cReadType(t, false);
|
|
|
+ DataType dt = cReadExtendedType(t, false);
|
|
|
if(dtIsVoid(dt)) {
|
|
|
return false;
|
|
|
}
|
|
@@ -927,10 +852,8 @@ static void cLineExpression() {
|
|
|
if(cDeclaration(t)) {
|
|
|
return;
|
|
|
}
|
|
|
- switch(t) {
|
|
|
- case T_DELETE: cDelete(); break;
|
|
|
- default: tReset(marker); cSetVariable();
|
|
|
- }
|
|
|
+ tReset(marker);
|
|
|
+ cSetVariable();
|
|
|
}
|
|
|
|
|
|
static void cFor() {
|
|
@@ -941,7 +864,7 @@ static void cFor() {
|
|
|
cLineExpression();
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
int startCheck = code->length;
|
|
|
- cExpectType(cUnpackedExpression(), dtBool(), "for");
|
|
|
+ cExpectType(cExpression(), dtInt(), "for");
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
cAddOperation(OP_IF_GOTO);
|
|
|
int32 end = cReserveInt32();
|
|
@@ -1006,6 +929,9 @@ static void cLine() {
|
|
|
}
|
|
|
|
|
|
static void cBuildFunction(Function* f, DataType rType, const char* name) {
|
|
|
+ if(rType.type == DT_STRUCT && rType.array == 0) {
|
|
|
+ cError("structs cannot be returned");
|
|
|
+ }
|
|
|
fInit(f, name, line);
|
|
|
f->returnType = rType;
|
|
|
vsReset(&vars);
|
|
@@ -1014,12 +940,15 @@ static void cBuildFunction(Function* f, DataType rType, const char* name) {
|
|
|
return;
|
|
|
}
|
|
|
while(true) {
|
|
|
- DataType dt = cReadType(cReadTokenAndLine(), true);
|
|
|
+ DataType dt = cReadExtendedType(cReadTokenAndLine(), true);
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
|
if(vsInScope(&vars, name)) {
|
|
|
cDeclared(name);
|
|
|
}
|
|
|
+ if(dt.type == DT_STRUCT) {
|
|
|
+ dt = dtToPointer(dt);
|
|
|
+ }
|
|
|
vsAdd(&vars, name, dt, &structs);
|
|
|
if(fAddArgument(f, dt, &structs)) {
|
|
|
cTooMuchArguments();
|
|
@@ -1065,7 +994,7 @@ static void cInnerFunction(Function* f) {
|
|
|
static void cFunction(DataType rType, const char* name) {
|
|
|
Function f;
|
|
|
cBuildFunction(&f, rType, name);
|
|
|
- Function* found = fsSearch(&functions, &f, true);
|
|
|
+ Function* found = fsSearch(&functions, &f);
|
|
|
if(cConsumeTokenIf(T_SEMICOLON)) {
|
|
|
cAddFunction(found, &f);
|
|
|
return;
|
|
@@ -1090,7 +1019,7 @@ static void cStruct() {
|
|
|
DataType self = dtStruct(st);
|
|
|
cConsumeToken(T_OPEN_CURVED_BRACKET);
|
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
|
- DataType dt = cReadType(cReadTokenAndLine(), true);
|
|
|
+ DataType dt = cReadExtendedType(cReadTokenAndLine(), true);
|
|
|
if(dtCompare(dt, self)) {
|
|
|
cError("struct %s contains itself", name);
|
|
|
}
|
|
@@ -1108,7 +1037,7 @@ static void cGlobalScope(Token t) {
|
|
|
}
|
|
|
DataType dt = dtVoid();
|
|
|
if(t != T_VOID) {
|
|
|
- dt = cReadType(t, true);
|
|
|
+ dt = cReadExtendedType(t, true);
|
|
|
}
|
|
|
cConsumeToken(T_LITERAL);
|
|
|
const char* name = cReadString();
|
|
@@ -1123,9 +1052,9 @@ static void cGlobalScope(Token t) {
|
|
|
static void cCallMain() {
|
|
|
Function f;
|
|
|
fInit(&f, "main", line);
|
|
|
- Function* found = fsSearch(&functions, &f, true);
|
|
|
+ Function* found = fsSearch(&functions, &f);
|
|
|
if(found != NULL && dtIsVoid(found->returnType)) {
|
|
|
- cAddInt32Operation(OP_PUSH_INT32, 0);
|
|
|
+ cAddInt32Operation(OP_PUSH_INT, 0);
|
|
|
cAddInt32Operation(OP_GOSUB, found->address);
|
|
|
cAddInt32(found->size);
|
|
|
}
|
|
@@ -1149,26 +1078,17 @@ static void cForEachLine() {
|
|
|
static void cLinkQueuedFunctions() {
|
|
|
for(int i = 0; i < functionQueue.entries; i++) {
|
|
|
Function* f = functionQueue.data + i;
|
|
|
- Function* found = fsSearch(&functions, f, false);
|
|
|
+ Function* found = fsSearch(&functions, f);
|
|
|
if(found == NULL || found->address == -1) {
|
|
|
line = f->line;
|
|
|
- cError("unknown function");
|
|
|
+ cUnknownFunction(f);
|
|
|
}
|
|
|
cSetInt32(f->address, found->address);
|
|
|
}
|
|
|
-}*/
|
|
|
-
|
|
|
-static void cScanForFunctions() {
|
|
|
-
|
|
|
- Token t = cReadTokenAndLine();
|
|
|
- if(t == T_END) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }*/
|
|
|
}
|
|
|
|
|
|
static void cAllocAndCompile() {
|
|
|
-
|
|
|
+ forWhileStack = 0;
|
|
|
breakIndex = 0;
|
|
|
returnType = dtVoid();
|
|
|
onLine = false;
|
|
@@ -1176,17 +1096,16 @@ static void cAllocAndCompile() {
|
|
|
vsInit(&globalVars);
|
|
|
fsInit(&functions);
|
|
|
fsInit(&functionQueue);
|
|
|
- stsInit(&structs);*/
|
|
|
+ stsInit(&structs);
|
|
|
if(!setjmp(errorJump)) {
|
|
|
- cScanForFunctions();
|
|
|
-
|
|
|
-
|
|
|
+ cForEachLine();
|
|
|
+ cLinkQueuedFunctions();
|
|
|
}
|
|
|
-
|
|
|
+ stsDelete(&structs);
|
|
|
fsDelete(&functionQueue);
|
|
|
fsDelete(&functions);
|
|
|
vsDelete(&globalVars);
|
|
|
- vsDelete(&vars);*/
|
|
|
+ vsDelete(&vars);
|
|
|
}
|
|
|
|
|
|
ByteCode* cCompile() {
|