|
@@ -8,7 +8,6 @@
|
|
|
#include "DataType.h"
|
|
|
#include "tokenizer/Tokenizer.h"
|
|
|
#include "utils/Functions.h"
|
|
|
-#include "utils/Structs.h"
|
|
|
#include "utils/Variables.h"
|
|
|
#include "vm/Operation.h"
|
|
|
|
|
@@ -31,7 +30,7 @@ static Structs structs;
|
|
|
static int returns[RETURN_BUFFER];
|
|
|
static int returnIndex = 0;
|
|
|
static bool hasReturn = false;
|
|
|
-static DataType returnType = DT_VOID;
|
|
|
+static DataType returnType;
|
|
|
|
|
|
static int breaks[BREAK_BUFFER];
|
|
|
static int breakIndex = 0;
|
|
@@ -78,10 +77,7 @@ static void cError(const char* format, ...) {
|
|
|
}
|
|
|
|
|
|
static const char* cGetName(DataType dt) {
|
|
|
- if(dtIsStruct(dt)) {
|
|
|
- return structs.data[dt - STRUCT_OFFSET].name;
|
|
|
- }
|
|
|
- return dtGetName(dt);
|
|
|
+ return dtGetName(&structs, dt);
|
|
|
}
|
|
|
|
|
|
static void cInvalidOperation(DataType a, DataType b, const char* op) {
|
|
@@ -213,7 +209,7 @@ static DataType cCallFunction(const char* name) {
|
|
|
}
|
|
|
|
|
|
static DataType cLoadVariable(Variable* v) {
|
|
|
- switch(v->type) {
|
|
|
+ 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;
|
|
@@ -224,10 +220,10 @@ static DataType cLoadVariable(Variable* v) {
|
|
|
}
|
|
|
|
|
|
static void cStoreVariable(Variable* v, DataType dt, const char* name) {
|
|
|
- if(v->type != dt) {
|
|
|
+ if(!dtCompare(v->type, dt)) {
|
|
|
cInvalidOperation(v->type, dt, name);
|
|
|
}
|
|
|
- switch(v->type) {
|
|
|
+ switch(dtAsInt(v->type)) {
|
|
|
case DT_INT: cAddOperation(OP_STORE_INT); break;
|
|
|
case DT_BOOL: cAddOperation(OP_STORE_BOOL); break;
|
|
|
case DT_FLOAT: cAddOperation(OP_STORE_FLOAT); break;
|
|
@@ -242,7 +238,7 @@ static void cStoreVariable(Variable* v, DataType dt, const char* name) {
|
|
|
}
|
|
|
|
|
|
static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
- if(v->type != DT_INT) {
|
|
|
+ if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
@@ -254,14 +250,14 @@ static DataType cPostChange(Variable* v, int change, const char* name) {
|
|
|
cAddOperation(OP_ADD_INT);
|
|
|
cAddOperation(OP_STORE_INT);
|
|
|
cAddInt(v->address);
|
|
|
- return DT_INT;
|
|
|
+ return dtInt();
|
|
|
}
|
|
|
|
|
|
static DataType cLiteral() {
|
|
|
const char* literal = cReadString();
|
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
DataType dt = cCallFunction(literal);
|
|
|
- if(dt == DT_VOID) {
|
|
|
+ if(dtCompare(dt, dtVoid())) {
|
|
|
cError("function returns void");
|
|
|
}
|
|
|
return dt;
|
|
@@ -287,25 +283,25 @@ static DataType cBracketPrimary() {
|
|
|
static DataType cAllocArray(DataType dt, Operation op) {
|
|
|
cConsumeToken(T_OPEN_SQUARE_BRACKET);
|
|
|
DataType index = cExpression();
|
|
|
- if(index != DT_INT) {
|
|
|
+ if(!dtCompare(index, dtInt())) {
|
|
|
cError("array size must be an int");
|
|
|
}
|
|
|
cConsumeToken(T_CLOSE_SQUARE_BRACKET);
|
|
|
cAddOperation(op);
|
|
|
- return dtArray(dt, 1);
|
|
|
+ return dtToArray(dt, 1);
|
|
|
}
|
|
|
|
|
|
static DataType cPrimary() {
|
|
|
Token t = cReadTokenAndLine();
|
|
|
switch(t) {
|
|
|
- case T_CONST_INT: cConstantInt(); return DT_INT;
|
|
|
- case T_CONST_FLOAT: cConstantFloat(); return DT_FLOAT;
|
|
|
- case T_TRUE: cAddOperation(OP_PUSH_TRUE); return DT_BOOL;
|
|
|
- case T_FALSE: cAddOperation(OP_PUSH_FALSE); return DT_BOOL;
|
|
|
+ case T_CONST_INT: cConstantInt(); return dtInt();
|
|
|
+ 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_OPEN_BRACKET: return cBracketPrimary();
|
|
|
case T_LITERAL: return cLiteral();
|
|
|
- case T_INT: return cAllocArray(DT_INT, OP_INT_ARRAY);
|
|
|
- default: cUnexpectedToken(t); return DT_VOID;
|
|
|
+ case T_INT: return cAllocArray(dtInt(), OP_INT_ARRAY);
|
|
|
+ default: cUnexpectedToken(t); return dtVoid();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -315,7 +311,7 @@ static DataType cPreChange(int change, const char* name) {
|
|
|
Variable* v = vSearch(&vars, literal);
|
|
|
if(v == NULL) {
|
|
|
cNotDeclared(literal);
|
|
|
- } else if(v->type != DT_INT) {
|
|
|
+ } else if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
@@ -327,13 +323,13 @@ static DataType cPreChange(int change, const char* name) {
|
|
|
cAddInt(v->address);
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
|
cAddInt(v->address);
|
|
|
- return DT_INT;
|
|
|
+ return dtInt();
|
|
|
}
|
|
|
|
|
|
static DataType cPreUnary() {
|
|
|
if(cConsumeTokenIf(T_SUB)) {
|
|
|
DataType result = cPrimary();
|
|
|
- switch(result) {
|
|
|
+ switch(dtAsInt(result)) {
|
|
|
case DT_INT: cAddOperation(OP_INVERT_SIGN_INT); break;
|
|
|
case DT_FLOAT: cAddOperation(OP_INVERT_SIGN_FLOAT); break;
|
|
|
default: cError("cannot invert sign of %s", cGetName(result));
|
|
@@ -349,17 +345,17 @@ static DataType cPreUnary() {
|
|
|
counter++;
|
|
|
}
|
|
|
DataType result = cPrimary();
|
|
|
- if(result != DT_BOOL) {
|
|
|
+ if(!dtCompare(result, dtBool())) {
|
|
|
cError("! needs a bool not %s", cGetName(result));
|
|
|
}
|
|
|
cAddOperation(OP_NOT);
|
|
|
if((counter & 1) == 0) {
|
|
|
cAddOperation(OP_NOT);
|
|
|
}
|
|
|
- return DT_BOOL;
|
|
|
+ return dtBool();
|
|
|
} else if(cConsumeTokenIf(T_BIT_NOT)) {
|
|
|
DataType result = cPrimary();
|
|
|
- if(result == DT_INT) {
|
|
|
+ if(dtCompare(result, dtInt())) {
|
|
|
cAddOperation(OP_BIT_NOT);
|
|
|
} else {
|
|
|
cError("~ needs an int not %s", cGetName(result));
|
|
@@ -370,11 +366,14 @@ static DataType cPreUnary() {
|
|
|
}
|
|
|
|
|
|
static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
|
|
|
- if(a == DT_INT && b == DT_INT && op->intOp != OP_NOTHING) {
|
|
|
+ if(dtCompare(a, dtInt()) && dtCompare(b, dtInt()) &&
|
|
|
+ op->intOp != OP_NOTHING) {
|
|
|
cAddOperation(op->intOp);
|
|
|
- } else if(a == DT_FLOAT && b == DT_FLOAT && op->floatOp != OP_NOTHING) {
|
|
|
+ } else if(dtCompare(a, dtFloat()) && dtCompare(b, dtFloat()) &&
|
|
|
+ op->floatOp != OP_NOTHING) {
|
|
|
cAddOperation(op->floatOp);
|
|
|
- } else if(a == DT_BOOL && b == DT_BOOL && op->boolOp != OP_NOTHING) {
|
|
|
+ } else if(dtCompare(a, dtBool()) && dtCompare(b, dtBool()) &&
|
|
|
+ op->boolOp != OP_NOTHING) {
|
|
|
cAddOperation(op->boolOp);
|
|
|
} else {
|
|
|
cInvalidOperation(a, b, op->name);
|
|
@@ -430,18 +429,18 @@ static DataType cComparison() {
|
|
|
while(true) {
|
|
|
if(cConsumeTokenIf(T_LESS)) {
|
|
|
cAddTypeOperation(a, cShift(), &TYPED_LESS);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else if(cConsumeTokenIf(T_LESS_EQUAL)) {
|
|
|
cAddTypeOperation(a, cShift(), &TYPED_LESS_EQUAL);
|
|
|
cAddOperation(OP_NOT);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else if(cConsumeTokenIf(T_GREATER)) {
|
|
|
cAddTypeOperation(a, cShift(), &TYPED_GREATER);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
|
|
|
cAddTypeOperation(a, cShift(), &TYPED_GREATER_EQUAL);
|
|
|
cAddOperation(OP_NOT);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else {
|
|
|
break;
|
|
|
}
|
|
@@ -454,11 +453,11 @@ static DataType cEqual() {
|
|
|
while(true) {
|
|
|
if(cConsumeTokenIf(T_EQUAL)) {
|
|
|
cAddTypeOperation(a, cComparison(), &TYPED_EQUAL);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else if(cConsumeTokenIf(T_NOT_EQUAL)) {
|
|
|
cAddTypeOperation(a, cComparison(), &TYPED_NOT_EQUAL);
|
|
|
cAddOperation(OP_NOT);
|
|
|
- a = DT_BOOL;
|
|
|
+ a = dtBool();
|
|
|
} else {
|
|
|
break;
|
|
|
}
|
|
@@ -499,7 +498,7 @@ static DataType cAnd() {
|
|
|
cAddOperation(OP_PEEK_FALSE_GOTO);
|
|
|
int p = cReserveInt();
|
|
|
DataType b = cBitOr();
|
|
|
- if(a != DT_BOOL || b != DT_BOOL) {
|
|
|
+ if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
|
cInvalidOperation(a, b, "&&");
|
|
|
}
|
|
|
cAddOperation(OP_AND);
|
|
@@ -514,7 +513,7 @@ static DataType cOr() {
|
|
|
cAddOperation(OP_PEEK_TRUE_GOTO);
|
|
|
int p = cReserveInt();
|
|
|
DataType b = cAnd();
|
|
|
- if(a != DT_BOOL || b != DT_BOOL) {
|
|
|
+ if(!dtCompare(a, dtBool()) || !dtCompare(b, dtBool())) {
|
|
|
cInvalidOperation(a, b, "||");
|
|
|
}
|
|
|
cAddOperation(OP_OR);
|
|
@@ -535,7 +534,7 @@ static void cOperationSet(Variable* v, const TypedOp* op) {
|
|
|
}
|
|
|
|
|
|
static void cAddPostLineChange(Variable* v, int change, const char* name) {
|
|
|
- if(v->type != DT_INT) {
|
|
|
+ if(!dtCompare(v->type, dtInt())) {
|
|
|
cError("%s needs an int", name);
|
|
|
}
|
|
|
cAddOperation(OP_LOAD_INT);
|
|
@@ -554,7 +553,7 @@ static void cDeclareStruct(Struct* st) {
|
|
|
if(v != NULL) {
|
|
|
cDeclared(var);
|
|
|
}
|
|
|
- vAdd(&vars, var, dtStruct(st->id));
|
|
|
+ vAdd(&vars, var, dtStruct(st));
|
|
|
int varLength = strlen(var);
|
|
|
for(int i = 0; i < st->amount; i++) {
|
|
|
int length = strlen(st->vars[i].name);
|
|
@@ -571,7 +570,7 @@ static void cLineLiteral() {
|
|
|
const char* literal = cReadString();
|
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
DataType dt = cCallFunction(literal);
|
|
|
- if(dt != DT_VOID) {
|
|
|
+ if(!dtCompare(dt, dtVoid())) {
|
|
|
cError("function returns %s not void", cGetName(dt));
|
|
|
}
|
|
|
return;
|
|
@@ -635,16 +634,16 @@ static void cReturn() {
|
|
|
cError("too much returns in function");
|
|
|
}
|
|
|
hasReturn = true;
|
|
|
- if(returnType == DT_VOID) {
|
|
|
+ if(dtCompare(returnType, dtVoid())) {
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
cAddReturn(OP_RETURN);
|
|
|
return;
|
|
|
}
|
|
|
DataType dt = cExpression();
|
|
|
- if(dt != returnType) {
|
|
|
+ if(!dtCompare(dt, returnType)) {
|
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
|
}
|
|
|
- switch(dt) {
|
|
|
+ switch(dtAsInt(dt)) {
|
|
|
case DT_INT: cAddReturn(OP_RETURN_INT); break;
|
|
|
case DT_BOOL: cAddReturn(OP_RETURN_BOOL); break;
|
|
|
case DT_FLOAT: cAddReturn(OP_RETURN_FLOAT); break;
|
|
@@ -655,7 +654,7 @@ static void cReturn() {
|
|
|
|
|
|
static void cPrint() {
|
|
|
DataType dt = cExpression();
|
|
|
- switch(dt) {
|
|
|
+ switch(dtAsInt(dt)) {
|
|
|
case DT_INT: cAddOperation(OP_PRINT_INT); break;
|
|
|
case DT_FLOAT: cAddOperation(OP_PRINT_FLOAT); break;
|
|
|
case DT_BOOL: cAddOperation(OP_PRINT_BOOL); break;
|
|
@@ -667,7 +666,7 @@ static void cPrint() {
|
|
|
static void cIf() {
|
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
|
DataType dt = cExpression();
|
|
|
- if(dt != DT_BOOL) {
|
|
|
+ if(!dtCompare(dt, dtBool())) {
|
|
|
cError("if expects a bool not %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
@@ -702,7 +701,7 @@ static void cWhile() {
|
|
|
int start = code->length;
|
|
|
cConsumeToken(T_OPEN_BRACKET);
|
|
|
DataType dt = cExpression();
|
|
|
- if(dt != DT_BOOL) {
|
|
|
+ if(!dtCompare(dt, dtBool())) {
|
|
|
cError("while expects a bool not %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
@@ -728,7 +727,7 @@ static DataType cDimension(DataType dt) {
|
|
|
dimension++;
|
|
|
}
|
|
|
if(dimension > 0) {
|
|
|
- dt = dtArray(dt, dimension);
|
|
|
+ dt = dtToArray(dt, dimension);
|
|
|
}
|
|
|
return dt;
|
|
|
}
|
|
@@ -759,9 +758,9 @@ static void cAddPreLineChange(int change, const char* name) {
|
|
|
static void cLineExpression(Token t) {
|
|
|
switch(t) {
|
|
|
case T_LITERAL: cLineLiteral(); break;
|
|
|
- case T_INT: cDeclare(DT_INT); break;
|
|
|
- case T_BOOL: cDeclare(DT_BOOL); break;
|
|
|
- case T_FLOAT: cDeclare(DT_FLOAT); 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;
|
|
|
default: cUnexpectedToken(t);
|
|
@@ -777,7 +776,7 @@ static void cFor() {
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
|
int startCheck = code->length;
|
|
|
DataType dt = cExpression();
|
|
|
- if(dt != DT_BOOL) {
|
|
|
+ if(!dtCompare(dt, dtBool())) {
|
|
|
cError("for expects a bool not %s", cGetName(dt));
|
|
|
}
|
|
|
cConsumeToken(T_SEMICOLON);
|
|
@@ -871,9 +870,9 @@ static void cFunctionAddArgument(Function* f, DataType dt) {
|
|
|
static void cFunctionArgument(Function* f) {
|
|
|
Token t = cReadTokenAndLine();
|
|
|
switch(t) {
|
|
|
- case T_INT: cFunctionAddArgument(f, DT_INT); break;
|
|
|
- case T_FLOAT: cFunctionAddArgument(f, DT_FLOAT); break;
|
|
|
- case T_BOOL: cFunctionAddArgument(f, DT_BOOL); break;
|
|
|
+ case T_INT: cFunctionAddArgument(f, dtInt()); break;
|
|
|
+ case T_FLOAT: cFunctionAddArgument(f, dtFloat()); break;
|
|
|
+ case T_BOOL: cFunctionAddArgument(f, dtBool()); break;
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
|
}
|
|
@@ -911,7 +910,7 @@ static void cInnerFunction(Function* f) {
|
|
|
returnIndex = 0;
|
|
|
hasReturn = false;
|
|
|
cConsumeScope();
|
|
|
- if(returnType != DT_VOID && !hasReturn) {
|
|
|
+ if(!dtCompare(returnType, dtVoid()) && !hasReturn) {
|
|
|
cError("missing return");
|
|
|
}
|
|
|
cFree(p, vars.maxAddress);
|
|
@@ -973,11 +972,11 @@ static void cStruct() {
|
|
|
cConsumeToken(T_OPEN_CURVED_BRACKET);
|
|
|
while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
|
|
|
Token t = cReadTokenAndLine();
|
|
|
- DataType dt = DT_VOID;
|
|
|
+ DataType dt = dtVoid();
|
|
|
switch(t) {
|
|
|
- case T_INT: dt = DT_INT; break;
|
|
|
- case T_BOOL: dt = DT_BOOL; break;
|
|
|
- case T_FLOAT: dt = DT_FLOAT; break;
|
|
|
+ case T_INT: dt = dtInt(); break;
|
|
|
+ case T_BOOL: dt = dtBool(); break;
|
|
|
+ case T_FLOAT: dt = dtFloat(); break;
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
|
dt = cDimension(dt);
|
|
@@ -991,10 +990,10 @@ static void cStruct() {
|
|
|
|
|
|
static void cGlobalScope(Token t) {
|
|
|
switch(t) {
|
|
|
- case T_VOID: cFunction(DT_VOID); break;
|
|
|
- case T_INT: cFunction(DT_INT); break;
|
|
|
- case T_BOOL: cFunction(DT_BOOL); break;
|
|
|
- case T_FLOAT: cFunction(DT_FLOAT); break;
|
|
|
+ case T_VOID: cFunction(dtVoid()); break;
|
|
|
+ case T_INT: cFunction(dtInt()); break;
|
|
|
+ case T_BOOL: cFunction(dtBool()); break;
|
|
|
+ case T_FLOAT: cFunction(dtFloat()); break;
|
|
|
case T_STRUCT: cStruct(); break;
|
|
|
default: cUnexpectedToken(t);
|
|
|
}
|
|
@@ -1004,7 +1003,7 @@ static void cCallMain() {
|
|
|
Function f;
|
|
|
fInit(&f, "main", line);
|
|
|
Function* found = fsSearch(&functions, &f);
|
|
|
- if(found != NULL && found->returnType == DT_VOID) {
|
|
|
+ if(found != NULL && dtCompare(found->returnType, dtVoid())) {
|
|
|
cAddOperation(OP_PUSH_INT);
|
|
|
cAddInt(0);
|
|
|
cAddOperation(OP_GOSUB);
|
|
@@ -1029,7 +1028,7 @@ static void cLinkQueuedFunctions() {
|
|
|
if(found == NULL) {
|
|
|
line = f->line;
|
|
|
cError("unknown function");
|
|
|
- } else if(f->returnType != found->returnType) {
|
|
|
+ } else if(!dtCompare(f->returnType, found->returnType)) {
|
|
|
line = f->line;
|
|
|
cError("function return type is not %s", cGetName(f->returnType));
|
|
|
}
|
|
@@ -1040,6 +1039,7 @@ static void cLinkQueuedFunctions() {
|
|
|
static void cAllocAndCompile() {
|
|
|
forWhileStack = 0;
|
|
|
breakIndex = 0;
|
|
|
+ returnType = dtVoid();
|
|
|
vInit(&vars);
|
|
|
fsInit(&functions);
|
|
|
fsInit(&functionQueue);
|