Explorar o código

const, bytecode strings are const

Kajetan Johannes Hammerle %!s(int64=3) %!d(string=hai) anos
pai
achega
29e7c45e3f
Modificáronse 12 ficheiros con 213 adicións e 62 borrados
  1. 67 35
      Compiler.c
  2. 29 10
      DataType.c
  3. 4 1
      DataType.h
  4. 5 5
      Test.c
  5. 52 0
      tests/const
  6. 5 0
      tests/const.out
  7. 15 3
      tests/strings/string
  8. 3 0
      tests/strings/string.out
  9. 2 0
      tokenizer/Token.c
  10. 1 0
      tokenizer/Token.h
  11. 29 7
      utils/Functions.c
  12. 1 1
      utils/Functions.h

+ 67 - 35
Compiler.c

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

+ 29 - 10
DataType.c

@@ -23,6 +23,9 @@ static void dtAppend(const char* s) {
 const char* dtGetName(Structs* sts, DataType dt) {
     typeNameSwap = !typeNameSwap;
     typeNameIndex = 0;
+    if(dt.constant) {
+        dtAppend("const ");
+    }
     switch(dt.type) {
         case DT_INT32: dtAppend("int"); break;
         case DT_INT64: dtAppend("long"); break;
@@ -62,42 +65,42 @@ int dtGetSize(DataType dt, Structs* sts) {
 }
 
 DataType dtInt32() {
-    DataType dt = {DT_INT32, 0, 0};
+    DataType dt = {DT_INT32, 0, 0, 0};
     return dt;
 }
 
 DataType dtInt64() {
-    DataType dt = {DT_INT64, 0, 0};
+    DataType dt = {DT_INT64, 0, 0, 0};
     return dt;
 }
 
 DataType dtFloat() {
-    DataType dt = {DT_FLOAT, 0, 0};
+    DataType dt = {DT_FLOAT, 0, 0, 0};
     return dt;
 }
 
 DataType dtBool() {
-    DataType dt = {DT_BOOL, 0, 0};
+    DataType dt = {DT_BOOL, 0, 0, 0};
     return dt;
 }
 
 DataType dtNull() {
-    DataType dt = {DT_NULL, 0, 0};
+    DataType dt = {DT_NULL, 0, 0, 0};
     return dt;
 }
 
 DataType dtText() {
-    DataType dt = {DT_INT32, 1, 0};
+    DataType dt = {DT_INT32, 1, 0, 0};
     return dt;
 }
 
 DataType dtVoid() {
-    DataType dt = {DT_VOID, 0, 0};
+    DataType dt = {DT_VOID, 0, 0, 0};
     return dt;
 }
 
 DataType dtStruct(Struct* st) {
-    DataType dt = {DT_STRUCT, 0, st->id};
+    DataType dt = {DT_STRUCT, 0, 0, st->id};
     return dt;
 }
 
@@ -114,9 +117,19 @@ bool dtDereference(DataType* dt) {
     return false;
 }
 
-bool dtCompare(DataType a, DataType b) {
+static bool dtInternCompare(DataType a, DataType b) {
     return a.pointers == b.pointers && a.structId == b.structId &&
-           a.type == b.type;
+           a.type == b.type && a.constant == b.constant;
+}
+
+bool dtCompare(DataType a, DataType b) {
+    return dtInternCompare(a, b);
+}
+
+bool dtNullCompare(DataType a, DataType bOrNull) {
+    return dtInternCompare(a, bOrNull) ||
+           (dtIsPointer(a) && dtIsNull(bOrNull) &&
+            a.constant == bOrNull.constant);
 }
 
 bool dtIsInt32(DataType dt) {
@@ -136,6 +149,7 @@ bool dtIsBool(DataType dt) {
 }
 
 bool dtIsNull(DataType dt) {
+    dt.constant = 0;
     return dtCompare(dt, dtNull());
 }
 
@@ -171,6 +185,11 @@ bool dtRemoveVariable(DataType* dt) {
     return false;
 }
 
+DataType dtConst(DataType dt) {
+    dt.constant = 1;
+    return dt;
+}
+
 void stAddVariable(Struct* st, const char* name, DataType type) {
     int index = st->amount;
     st->amount++;

+ 4 - 1
DataType.h

@@ -16,7 +16,8 @@
 typedef struct {
     unsigned int type : 4;
     unsigned int pointers : 4;
-    unsigned int structId : 24;
+    unsigned int constant : 1;
+    unsigned int structId : 23;
 } DataType;
 
 typedef struct {
@@ -58,8 +59,10 @@ bool dtDereference(DataType* dt);
 Struct* dtGetStruct(Structs* sts, DataType dt);
 DataType dtToVariable(DataType dt);
 bool dtRemoveVariable(DataType* dt);
+DataType dtConst(DataType dt);
 
 bool dtCompare(DataType a, DataType b);
+bool dtNullCompare(DataType a, DataType bOrNull);
 bool dtIsInt32(DataType dt);
 bool dtIsInt64(DataType dt);
 bool dtIsFloat(DataType dt);

+ 5 - 5
Test.c

@@ -190,11 +190,11 @@ static void tsAddPrinter(Structs* sts, DataType in, ScriptFunction sf) {
 void tsStart(const char* path) {
     Structs sts;
     stsInit(&sts);
-    tsAddPrinter(&sts, dtInt32(), tsInt32Printer);
-    tsAddPrinter(&sts, dtInt64(), tsInt64Printer);
-    tsAddPrinter(&sts, dtFloat(), tsFloatPrinter);
-    tsAddPrinter(&sts, dtBool(), tsBoolPrinter);
-    tsAddPrinter(&sts, dtText(), tsTextPrinter);
+    tsAddPrinter(&sts, dtConst(dtInt32()), tsInt32Printer);
+    tsAddPrinter(&sts, dtConst(dtInt64()), tsInt64Printer);
+    tsAddPrinter(&sts, dtConst(dtFloat()), tsFloatPrinter);
+    tsAddPrinter(&sts, dtConst(dtBool()), tsBoolPrinter);
+    tsAddPrinter(&sts, dtConst(dtText()), tsTextPrinter);
 
     doneTests = 0;
     allTests = 0;

+ 52 - 0
tests/const

@@ -0,0 +1,52 @@
+const int* wusi(int i) {
+    return &i;
+}
+
+const int wusi2(int i) {
+    return i;
+}
+
+struct B {
+    int b;
+};
+
+struct A {
+    int a;
+    B b;
+};
+
+void wusi(const A* a) {
+    //a->a += 3;
+    //a->b.b += 3;
+    test(a->a);
+    test(a->b.b);
+}
+
+void main() {
+    const int i = 3;
+    const int* w = &i;
+    int a = i;
+    a = i;
+    const int* b = nullptr;
+    const int** c = &b;
+    const int* d = *c;
+    b = wusi(3);
+    a = wusi2(3);
+    
+    int* test = new int[5];
+    delete test;
+    
+    //i += 3;
+    
+    int* e = nullptr;
+    
+    test(i + 1);
+    
+    test(e == d);
+    test(e != d);
+    
+    A s;
+    s.a = 3;
+    s.b.b = 5;
+    wusi(&s);
+}

+ 5 - 0
tests/const.out

@@ -0,0 +1,5 @@
+4
+true
+false
+3
+5

+ 15 - 3
tests/strings/string

@@ -1,7 +1,15 @@
+void wusi(const int** b) {
+    test("Const Wusi");
+}
+
+void wusi(int** b) {
+    test("Wusi");
+}
+
 void main() {
-    int* a = "öallo";
-    a[0] = 'H';
-    int** b = &a; 
+    const int* a = "2allo";
+    a = "Hallo";
+    const int** b = &a; 
     test(a == *b);
     test(*a);
     test(a[0]);
@@ -11,4 +19,8 @@ void main() {
     test(a[4]);
     test(a);
     test(length(a));
+    int** n = nullptr;
+    wusi(n);
+    wusi(nullptr);
+    wusi(b);
 }

+ 3 - 0
tests/strings/string.out

@@ -7,3 +7,6 @@ true
 111
 Hallo
 5
+Wusi
+Wusi
+Const Wusi

+ 2 - 0
tokenizer/Token.c

@@ -72,6 +72,7 @@ const char* tGetName(Token token) {
         case T_NEW: return "new";
         case T_DELETE: return "delete";
         case T_LENGTH: return "length";
+        case T_CONST: return "const";
         case T_END: return "end";
     }
     return "unknown";
@@ -102,5 +103,6 @@ Token tFromName(const char* name) {
     MATCH_TOKEN("new", T_NEW);
     MATCH_TOKEN("delete", T_DELETE);
     MATCH_TOKEN("length", T_LENGTH);
+    MATCH_TOKEN("const", T_CONST);
     return T_END;
 }

+ 1 - 0
tokenizer/Token.h

@@ -69,6 +69,7 @@ typedef enum {
     T_NEW,
     T_DELETE,
     T_LENGTH,
+    T_CONST,
     T_END
 } Token;
 

+ 29 - 7
utils/Functions.c

@@ -26,12 +26,26 @@ bool fAddArgument(Function* f, DataType type, Structs* sts) {
     return false;
 }
 
-bool fCompare(Function* a, Function* b) {
+static bool fConstCompare(Function* a, Function* b) {
     if(a->arguments != b->arguments) {
         return false;
     }
     for(int i = 0; i < a->arguments; i++) {
-        if(!dtCompare(a->argumentTypes[i], b->argumentTypes[i])) {
+        if(!dtNullCompare(a->argumentTypes[i], b->argumentTypes[i])) {
+            return false;
+        }
+    }
+    return strcmp(a->name, b->name) == 0;
+}
+
+static bool fCompare(Function* a, Function* b) {
+    if(a->arguments != b->arguments || strcmp(a->name, b->name) != 0) {
+        return false;
+    }
+    for(int i = 0; i < a->arguments; i++) {
+        DataType dt = b->argumentTypes[i];
+        if(!dtNullCompare(a->argumentTypes[i], dt) &&
+           !dtNullCompare(a->argumentTypes[i], dtConst(dt))) {
             return false;
         }
     }
@@ -48,7 +62,15 @@ void fsDelete(Functions* fs) {
     free(fs->data);
 }
 
-static Function* fsInternSearch(Functions* fs, Function* f) {
+static Function* fsInternSearch(Functions* fs, Function* f, bool constMatch) {
+    for(int i = 0; i < fs->entries; i++) {
+        if(fConstCompare(fs->data + i, f)) {
+            return fs->data + i;
+        }
+    }
+    if(constMatch) {
+        return NULL;
+    }
     for(int i = 0; i < fs->entries; i++) {
         if(fCompare(fs->data + i, f)) {
             return fs->data + i;
@@ -57,14 +79,14 @@ static Function* fsInternSearch(Functions* fs, Function* f) {
     return NULL;
 }
 
-Function* fsSearch(Functions* fs, Function* f) {
+Function* fsSearch(Functions* fs, Function* f, bool constMatch) {
     if(useGlobals) {
-        Function* gf = fsInternSearch(&globalFunctions, f);
+        Function* gf = fsInternSearch(&globalFunctions, f, constMatch);
         if(gf != NULL) {
             return gf;
         }
     }
-    return fsInternSearch(fs, f);
+    return fsInternSearch(fs, f, constMatch);
 }
 
 void fsAdd(Functions* fs, Function* f) {
@@ -87,7 +109,7 @@ void gfsInit() {
 }
 
 bool gfsAdd(Function* f) {
-    if(fsSearch(&globalFunctions, f) != NULL) {
+    if(fsSearch(&globalFunctions, f, true) != NULL) {
         return true;
     }
     int index = globalFunctions.entries;

+ 1 - 1
utils/Functions.h

@@ -33,7 +33,7 @@ bool fAddArgument(Function* f, DataType type, Structs* sts);
 
 void fsInit(Functions* fs);
 void fsDelete(Functions* fs);
-Function* fsSearch(Functions* fs, Function* f);
+Function* fsSearch(Functions* fs, Function* f, bool constMatch);
 void fsAdd(Functions* fs, Function* f);
 
 void gfInit(Function* f, const char* name, DataType r, ScriptFunction sf);