|
@@ -209,26 +209,33 @@ static DataType cDereference(DataType dt) {
|
|
return dt;
|
|
return dt;
|
|
}
|
|
}
|
|
|
|
|
|
-static DataType cExtendType(DataType dt) {
|
|
|
|
|
|
+static DataType cExtendType(DataType dt, bool constant) {
|
|
while(cConsumeTokenIf(T_MUL)) {
|
|
while(cConsumeTokenIf(T_MUL)) {
|
|
dt = cDereference(dt);
|
|
dt = cDereference(dt);
|
|
}
|
|
}
|
|
|
|
+ if(constant) {
|
|
|
|
+ dt = dtConst(dt);
|
|
|
|
+ }
|
|
return dt;
|
|
return dt;
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cReadType(Token t) {
|
|
static DataType cReadType(Token t) {
|
|
|
|
+ bool c = t == T_CONST;
|
|
|
|
+ if(c) {
|
|
|
|
+ t = cReadTokenAndLine();
|
|
|
|
+ }
|
|
switch(t) {
|
|
switch(t) {
|
|
- case T_INT32: return cExtendType(dtInt32());
|
|
|
|
- case T_INT64: return cExtendType(dtInt64());
|
|
|
|
- case T_BOOL: return cExtendType(dtBool());
|
|
|
|
- case T_FLOAT: return cExtendType(dtFloat());
|
|
|
|
|
|
+ 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_LITERAL:
|
|
case T_LITERAL:
|
|
{
|
|
{
|
|
Struct* st = stsSearch(&structs, cReadString());
|
|
Struct* st = stsSearch(&structs, cReadString());
|
|
if(st == NULL) {
|
|
if(st == NULL) {
|
|
cError("struct %s does not exist");
|
|
cError("struct %s does not exist");
|
|
}
|
|
}
|
|
- return cExtendType(dtStruct(st));
|
|
|
|
|
|
+ return cExtendType(dtStruct(st), c);
|
|
}
|
|
}
|
|
default: cUnexpectedToken(t); return dtVoid();
|
|
default: cUnexpectedToken(t); return dtVoid();
|
|
}
|
|
}
|
|
@@ -282,7 +289,7 @@ static DataType cCallFunction(const char* name) {
|
|
onLine = false;
|
|
onLine = false;
|
|
cCallFunctionArguments(&f);
|
|
cCallFunctionArguments(&f);
|
|
onLine = oldOnLine;
|
|
onLine = oldOnLine;
|
|
- Function* found = fsSearch(&functions, &f);
|
|
|
|
|
|
+ Function* found = fsSearch(&functions, &f, false);
|
|
if(found == NULL) {
|
|
if(found == NULL) {
|
|
cError("unknown function");
|
|
cError("unknown function");
|
|
} else if(found->global) {
|
|
} else if(found->global) {
|
|
@@ -303,17 +310,17 @@ static DataType cCallFunction(const char* name) {
|
|
return found->returnType;
|
|
return found->returnType;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool cCompare(DataType left, DataType right) {
|
|
|
|
- return dtCompare(left, right) || (dtIsPointer(left) && dtIsNull(right));
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void cStore(DataType left, DataType right, const char* name) {
|
|
static void cStore(DataType left, DataType right, const char* name) {
|
|
- if(!cCompare(left, right)) {
|
|
|
|
- cInvalidOperation(left, right, name);
|
|
|
|
- } else if(dtIsPointer(left)) {
|
|
|
|
|
|
+ if(dtIsPointer(left)) {
|
|
|
|
+ if(!dtNullCompare(left, right)) {
|
|
|
|
+ cInvalidOperation(left, right, name);
|
|
|
|
+ }
|
|
cAddOperation(OP_STORE_POINTER);
|
|
cAddOperation(OP_STORE_POINTER);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ if(!dtNullCompare(left, right) && !dtNullCompare(dtConst(left), right)) {
|
|
|
|
+ cInvalidOperation(left, right, name);
|
|
|
|
+ }
|
|
switch(left.type) {
|
|
switch(left.type) {
|
|
DT_OPERATION(STORE);
|
|
DT_OPERATION(STORE);
|
|
default: cError("cannot store type %s", cGetName(left));
|
|
default: cError("cannot store type %s", cGetName(left));
|
|
@@ -343,7 +350,7 @@ static DataType cText() {
|
|
length++;
|
|
length++;
|
|
}
|
|
}
|
|
cSetInt32(lengthAddress, length);
|
|
cSetInt32(lengthAddress, length);
|
|
- return dtText();
|
|
|
|
|
|
+ return dtConst(dtText());
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cBracketPrimary() {
|
|
static DataType cBracketPrimary() {
|
|
@@ -441,7 +448,9 @@ static DataType cStructAccess(DataType dt, int pointers) {
|
|
cAddInt32Operation(OP_PUSH_INT32, inner.address);
|
|
cAddInt32Operation(OP_PUSH_INT32, inner.address);
|
|
cAddInt32Operation(OP_ADD_REFERENCE, 1);
|
|
cAddInt32Operation(OP_ADD_REFERENCE, 1);
|
|
}
|
|
}
|
|
- return dtToVariable(inner.type);
|
|
|
|
|
|
+ DataType r = dtToVariable(inner.type);
|
|
|
|
+ r.constant = dt.constant;
|
|
|
|
+ return r;
|
|
}
|
|
}
|
|
|
|
|
|
static DataType cAccess() {
|
|
static DataType cAccess() {
|
|
@@ -570,6 +579,8 @@ static DataType cPreUnary() {
|
|
static void cAddTypeOperation(DataType* a, Parser bf, const TypedOp* op) {
|
|
static void cAddTypeOperation(DataType* a, Parser bf, const TypedOp* op) {
|
|
*a = cUnpack(*a);
|
|
*a = cUnpack(*a);
|
|
DataType b = cUnpack(bf());
|
|
DataType b = cUnpack(bf());
|
|
|
|
+ a->constant = 0;
|
|
|
|
+ b.constant = 0;
|
|
if(!dtCompare(*a, b)) {
|
|
if(!dtCompare(*a, b)) {
|
|
cInvalidOperation(*a, b, op->name);
|
|
cInvalidOperation(*a, b, op->name);
|
|
} else if(dtIsInt32(*a) && op->intOp != OP_NOTHING) {
|
|
} else if(dtIsInt32(*a) && op->intOp != OP_NOTHING) {
|
|
@@ -744,7 +755,8 @@ static void cReturn() {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
DataType dt = cUnpackedExpression();
|
|
DataType dt = cUnpackedExpression();
|
|
- if(!cCompare(returnType, dt)) {
|
|
|
|
|
|
+ if(!dtNullCompare(returnType, dt) &&
|
|
|
|
+ !dtNullCompare(returnType, dtConst(dt))) {
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
cError("wrong return type, should be %s", cGetName(returnType));
|
|
} else if(dtIsInt32(dt)) {
|
|
} else if(dtIsInt32(dt)) {
|
|
cAddReturn(OP_RETURN_INT32);
|
|
cAddReturn(OP_RETURN_INT32);
|
|
@@ -815,14 +827,17 @@ static void cWhile() {
|
|
|
|
|
|
static void cDelete() {
|
|
static void cDelete() {
|
|
DataType pointer = cUnpackedExpression();
|
|
DataType pointer = cUnpackedExpression();
|
|
- if(!dtIsPointer(pointer)) {
|
|
|
|
- cError("delete expects a pointer");
|
|
|
|
|
|
+ if(!dtIsPointer(pointer) || pointer.constant) {
|
|
|
|
+ cError("delete expects a non const pointer");
|
|
}
|
|
}
|
|
cAddOperation(OP_DELETE);
|
|
cAddOperation(OP_DELETE);
|
|
}
|
|
}
|
|
|
|
|
|
static void cOperationSet(DataType left, const TypedOp* op) {
|
|
static void cOperationSet(DataType left, const TypedOp* op) {
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
cAddOperation(OP_DUPLICATE_REFERENCE);
|
|
|
|
+ if(left.constant) {
|
|
|
|
+ cError("cannot use %s= on const reference", op->name);
|
|
|
|
+ }
|
|
cLoadRef(left);
|
|
cLoadRef(left);
|
|
cAddTypeOperation(&left, cUnpackedExpression, op);
|
|
cAddTypeOperation(&left, cUnpackedExpression, op);
|
|
cStore(left, left, "=");
|
|
cStore(left, left, "=");
|
|
@@ -853,8 +868,8 @@ static void cSetVariable() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void cDeclare(DataType dt) {
|
|
|
|
- dt = cExtendType(dt);
|
|
|
|
|
|
+static void cDeclare(DataType dt, bool constant) {
|
|
|
|
+ dt = cExtendType(dt, constant);
|
|
cConsumeToken(T_LITERAL);
|
|
cConsumeToken(T_LITERAL);
|
|
const char* var = cReadString();
|
|
const char* var = cReadString();
|
|
if(vsInScope(&vars, var)) {
|
|
if(vsInScope(&vars, var)) {
|
|
@@ -864,26 +879,44 @@ static void cDeclare(DataType dt) {
|
|
if(dt.type != DT_STRUCT || dtIsPointer(dt)) {
|
|
if(dt.type != DT_STRUCT || dtIsPointer(dt)) {
|
|
cConsumeToken(T_SET);
|
|
cConsumeToken(T_SET);
|
|
cAddInt32Operation(OP_DEREFERENCE_VAR, v->address);
|
|
cAddInt32Operation(OP_DEREFERENCE_VAR, v->address);
|
|
- cStore(v->type, cUnpackedExpression(), "=");
|
|
|
|
|
|
+ DataType right = cUnpackedExpression();
|
|
|
|
+ if(!right.constant) {
|
|
|
|
+ dt.constant = 0;
|
|
|
|
+ }
|
|
|
|
+ cStore(dt, right, "=");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void cLineExpression() {
|
|
|
|
- int marker = tGetMarker();
|
|
|
|
- Token t = cReadTokenAndLine();
|
|
|
|
|
|
+static bool cDeclaration(Token t) {
|
|
|
|
+ bool c = t == T_CONST;
|
|
|
|
+ if(c) {
|
|
|
|
+ t = cReadTokenAndLine();
|
|
|
|
+ }
|
|
if(t == T_LITERAL) {
|
|
if(t == T_LITERAL) {
|
|
const char* literal = cReadString();
|
|
const char* literal = cReadString();
|
|
Struct* st = stsSearch(&structs, literal);
|
|
Struct* st = stsSearch(&structs, literal);
|
|
if(st != NULL) {
|
|
if(st != NULL) {
|
|
- cDeclare(dtStruct(st));
|
|
|
|
- return;
|
|
|
|
|
|
+ cDeclare(dtStruct(st), c);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
switch(t) {
|
|
switch(t) {
|
|
- case T_INT32: cDeclare(dtInt32()); break;
|
|
|
|
- case T_INT64: cDeclare(dtInt64()); break;
|
|
|
|
- case T_BOOL: cDeclare(dtBool()); break;
|
|
|
|
- case T_FLOAT: cDeclare(dtFloat()); break;
|
|
|
|
|
|
+ case T_INT32: cDeclare(dtInt32(), c); break;
|
|
|
|
+ case T_INT64: cDeclare(dtInt64(), c); break;
|
|
|
|
+ case T_BOOL: cDeclare(dtBool(), c); break;
|
|
|
|
+ case T_FLOAT: cDeclare(dtFloat(), c); break;
|
|
|
|
+ default: return false;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cLineExpression() {
|
|
|
|
+ int marker = tGetMarker();
|
|
|
|
+ Token t = cReadTokenAndLine();
|
|
|
|
+ if(cDeclaration(t)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ switch(t) {
|
|
case T_DELETE: cDelete(); break;
|
|
case T_DELETE: cDelete(); break;
|
|
default: tReset(marker); cSetVariable();
|
|
default: tReset(marker); cSetVariable();
|
|
}
|
|
}
|
|
@@ -1020,10 +1053,9 @@ static void cInnerFunction(Function* f) {
|
|
}
|
|
}
|
|
|
|
|
|
static void cFunction(DataType rType) {
|
|
static void cFunction(DataType rType) {
|
|
- rType = cExtendType(rType);
|
|
|
|
Function f;
|
|
Function f;
|
|
cBuildFunction(&f, rType);
|
|
cBuildFunction(&f, rType);
|
|
- Function* found = fsSearch(&functions, &f);
|
|
|
|
|
|
+ Function* found = fsSearch(&functions, &f, true);
|
|
if(cConsumeTokenIf(T_SEMICOLON)) {
|
|
if(cConsumeTokenIf(T_SEMICOLON)) {
|
|
cAddFunction(found, &f);
|
|
cAddFunction(found, &f);
|
|
return;
|
|
return;
|
|
@@ -1070,7 +1102,7 @@ static void cGlobalScope(Token t) {
|
|
static void cCallMain() {
|
|
static void cCallMain() {
|
|
Function f;
|
|
Function f;
|
|
fInit(&f, "main", line);
|
|
fInit(&f, "main", line);
|
|
- Function* found = fsSearch(&functions, &f);
|
|
|
|
|
|
+ Function* found = fsSearch(&functions, &f, true);
|
|
if(found != NULL && dtIsVoid(found->returnType)) {
|
|
if(found != NULL && dtIsVoid(found->returnType)) {
|
|
cAddInt32Operation(OP_PUSH_INT32, 0);
|
|
cAddInt32Operation(OP_PUSH_INT32, 0);
|
|
cAddInt32Operation(OP_GOSUB, found->address);
|
|
cAddInt32Operation(OP_GOSUB, found->address);
|
|
@@ -1092,7 +1124,7 @@ static void cForEachLine() {
|
|
static void cLinkQueuedFunctions() {
|
|
static void cLinkQueuedFunctions() {
|
|
for(int i = 0; i < functionQueue.entries; i++) {
|
|
for(int i = 0; i < functionQueue.entries; i++) {
|
|
Function* f = functionQueue.data + i;
|
|
Function* f = functionQueue.data + i;
|
|
- Function* found = fsSearch(&functions, f);
|
|
|
|
|
|
+ Function* found = fsSearch(&functions, f, false);
|
|
if(found == NULL || found->address == -1) {
|
|
if(found == NULL || found->address == -1) {
|
|
line = f->line;
|
|
line = f->line;
|
|
cError("unknown function");
|
|
cError("unknown function");
|