瀏覽代碼

arrays, array tests, better increment / decrement

Kajetan Johannes Hammerle 3 年之前
父節點
當前提交
77fa3719d9

+ 97 - 74
Compiler.c

@@ -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);
     }
 }

+ 2 - 2
DataType.c

@@ -39,7 +39,7 @@ const char* dtGetName(Structs* sts, DataType dt) {
 
 int dtGetSize(DataType dt, Structs* sts) {
     if(dt.pointers > 0) {
-        return sizeof(int);
+        return sizeof(Pointer);
     }
     switch(dt.type) {
         case DT_INT: return sizeof(int);
@@ -54,7 +54,7 @@ int dtGetSize(DataType dt, Structs* sts) {
                 }
                 return size;
             }
-        default: return sizeof(int);
+        default: return 0;
     }
 }
 

+ 5 - 0
DataType.h

@@ -33,6 +33,11 @@ typedef struct {
     Struct* data;
 } Structs;
 
+typedef struct {
+    int array;
+    int offset;
+} Pointer;
+
 int dtGetSize(DataType dt, Structs* sts);
 
 DataType dtInt();

+ 5 - 21
Test.c

@@ -32,27 +32,6 @@ static void tsPrintToBuffer(const char* format, ...) {
     va_end(args);
 }
 
-/*static bool tsPrinter(Object* o) {
-    if(testBufferIndex >= TEST_BUFFER_LENGTH) {
-        return true;
-    }
-    switch(o->type) {
-        case OT_INT: tsPrintToBuffer("%d\n", o->as.intValue); return false;
-        case OT_FLOAT:
-            tsPrintToBuffer("%.2f\n", o->as.floatValue);
-            return false;
-        case OT_CONST_STRING:
-            tsPrintToBuffer("%s\n", o->as.stringValue);
-            return false;
-        case OT_NULL: tsPrintToBuffer("null\n"); return false;
-        case OT_BOOL:
-            tsPrintToBuffer(o->as.intValue ? "true\n" : "false\n");
-            return false;
-        case OT_ARRAY: tsPrintToBuffer("array\n"); return false;
-        default: return true;
-    }
-}*/
-
 static void tsIntPrinter(int i) {
     tsPrintToBuffer("%d\n", i);
 }
@@ -65,6 +44,10 @@ static void tsBoolPrinter(bool b) {
     tsPrintToBuffer(b ? "true\n" : "false\n");
 }
 
+static void tsPointerPrinter(Pointer* p) {
+    tsPrintToBuffer("(%d, %d)\n", p->array, p->offset);
+}
+
 static void tsAppend(const char* s) {
     for(int i = 0; pathIndex < (PATH_MAX - 1) && s[i] != '\0'; i++) {
         path[pathIndex++] = s[i];
@@ -171,6 +154,7 @@ void tsStart(const char* path) {
     sSetIntPrinter(tsIntPrinter);
     sSetFloatPrinter(tsFloatPrinter);
     sSetBoolPrinter(tsBoolPrinter);
+    sSetPointerPrinter(tsPointerPrinter);
     doneTests = 0;
     allTests = 0;
     tsAppend(path);

+ 0 - 6
old_tests/arrays/and

@@ -1,6 +0,0 @@
-a = array[1];
-a[0] = 7;
-a[0] &= 15;
-print a[0];
-a[0] &= 9;
-print a[0];

+ 0 - 8
old_tests/arrays/dec

@@ -1,8 +0,0 @@
-a = array[1];
-a[0] = 0;
-a[0]--;
---a[0];
-print a[0]--;
-print a[0]--;
-print --a[0];
-print --a[0];

+ 0 - 8
old_tests/arrays/inc

@@ -1,8 +0,0 @@
-a = array[1];
-a[0] = 0;
-a[0]++;
-++a[0];
-print a[0]++;
-print a[0]++;
-print ++a[0];
-print ++a[0];

+ 0 - 6
old_tests/arrays/or

@@ -1,6 +0,0 @@
-a = array[1];
-a[0] = 0;
-a[0] |= 2;
-print a[0];
-a[0] |= 5;
-print a[0];

+ 0 - 31
old_tests/arrays/setop

@@ -1,31 +0,0 @@
-a = array[1];
-
-a[0] = 5;
-a[0] += 5;
-a[0] += 10;
-a[0] += 20;
-print a[0];
-
-a[0] = 5;
-a[0] -= 5;
-a[0] -= -10;
-a[0] -= 20;
-print a[0];
-
-a[0] = 5;
-a[0] *= 2;
-a[0] *= 3;
-a[0] *= 4;
-print a[0];
-
-a[0] = 100;
-a[0] /= 2;
-a[0] /= 3;
-a[0] /= 4;
-print a[0];
-
-a[0] = 100;
-a[0] %= 120;
-a[0] %= 90;
-a[0] %= 3;
-print a[0];

+ 0 - 10
old_tests/arrays/shift

@@ -1,10 +0,0 @@
-a = array[1];
-a[0] = 1;
-a[0] <<= 2;
-a[0] <<= 3;
-print a[0];
-
-a[0] = 100;
-a[0] >>= 2;
-a[0] >>= 3;
-print a[0];

+ 0 - 6
old_tests/arrays/xor

@@ -1,6 +0,0 @@
-a = array[1];
-a[0] = 0;
-a[0] ^= 2;
-print a[0];
-a[0] ^= 7;
-print a[0];

+ 26 - 6
tests/arrays/alloc

@@ -1,11 +1,31 @@
 void main() {
-    /*int* a = int[4];
-    print a.length;
-    a[0] = 5;
-    a[1] = true;
-    a[2] = "Hi";
+    int start = 0;
+    int* a = new int[4];
+    int** b = &a;
+    int* c = *b;
+    print a == c;
+    print &start != a;
+    
+    print length(a);
+    print length(b);
+    print length(c);
+    
+    a[0] = 50;
+    a[1] = 60;
+    a[2] = 70;
+    a[3] = 80;
+    
     print a[0];
     print a[1];
     print a[2];
-    print a[3];*/
+    print a[3]; 
+       
+    print *a;
+    
+    
+    while(true) {
+        int* h = new int[5];
+    }
+    
+    delete a;
 }

+ 10 - 0
tests/arrays/alloc.out

@@ -0,0 +1,10 @@
+true
+true
+4
+1
+4
+50
+60
+70
+80
+50

+ 8 - 0
tests/arrays/and

@@ -0,0 +1,8 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 7;
+    a[0] &= 15;
+    print a[0];
+    a[0] &= 9;
+    print a[0];
+}

+ 0 - 0
old_tests/arrays/and.out → tests/arrays/and.out


+ 10 - 0
tests/arrays/dec

@@ -0,0 +1,10 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 0;
+    a[0]--;
+    --a[0];
+    print a[0]--;
+    print a[0]--;
+    print --a[0];
+    print --a[0];
+}

+ 0 - 0
old_tests/arrays/dec.out → tests/arrays/dec.out


+ 10 - 0
tests/arrays/inc

@@ -0,0 +1,10 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 0;
+    a[0]++;
+    ++a[0];
+    print a[0]++;
+    print a[0]++;
+    print ++a[0];
+    print ++a[0];
+}

+ 0 - 0
old_tests/arrays/inc.out → tests/arrays/inc.out


+ 8 - 0
tests/arrays/or

@@ -0,0 +1,8 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 0;
+    a[0] |= 2;
+    print a[0];
+    a[0] |= 5;
+    print a[0];
+}

+ 0 - 0
old_tests/arrays/or.out → tests/arrays/or.out


+ 33 - 0
tests/arrays/setop

@@ -0,0 +1,33 @@
+void main() {
+    int* a = new int[1];
+
+    a[0] = 5;
+    a[0] += 5;
+    a[0] += 10;
+    a[0] += 20;
+    print a[0];
+
+    a[0] = 5;
+    a[0] -= 5;
+    a[0] -= -10;
+    a[0] -= 20;
+    print a[0];
+
+    a[0] = 5;
+    a[0] *= 2;
+    a[0] *= 3;
+    a[0] *= 4;
+    print a[0];
+
+    a[0] = 100;
+    a[0] /= 2;
+    a[0] /= 3;
+    a[0] /= 4;
+    print a[0];
+
+    a[0] = 100;
+    a[0] %= 120;
+    a[0] %= 90;
+    a[0] %= 3;
+    print a[0];
+}

+ 0 - 0
old_tests/arrays/setop.out → tests/arrays/setop.out


+ 12 - 0
tests/arrays/shift

@@ -0,0 +1,12 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 1;
+    a[0] <<= 2;
+    a[0] <<= 3;
+    print a[0];
+
+    a[0] = 100;
+    a[0] >>= 2;
+    a[0] >>= 3;
+    print a[0];
+}

+ 0 - 0
old_tests/arrays/shift.out → tests/arrays/shift.out


+ 8 - 0
tests/arrays/xor

@@ -0,0 +1,8 @@
+void main() {
+    int* a = new int[1];
+    a[0] = 0;
+    a[0] ^= 2;
+    print a[0];
+    a[0] ^= 7;
+    print a[0];
+}

+ 0 - 0
old_tests/arrays/xor.out → tests/arrays/xor.out


+ 0 - 1
tests/struct/nested

@@ -10,7 +10,6 @@ struct B {
     A d;
 };
 
-
 void main() {
     B b;
     b.a = 1;

+ 6 - 0
tokenizer/Token.c

@@ -68,6 +68,9 @@ const char* tGetName(Token token) {
         case T_ARROW: return "->";
         case T_OPEN_SQUARE_BRACKET: return "[";
         case T_CLOSE_SQUARE_BRACKET: return "]";
+        case T_NEW: return "new";
+        case T_DELETE: return "delete";
+        case T_LENGTH: return "length";
         case T_END: return "end";
     }
     return "unknown";
@@ -95,5 +98,8 @@ Token tFromName(const char* name) {
     MATCH_TOKEN("bool", T_BOOL);
     MATCH_TOKEN("float", T_FLOAT);
     MATCH_TOKEN("struct", T_STRUCT);
+    MATCH_TOKEN("new", T_NEW);
+    MATCH_TOKEN("delete", T_DELETE);
+    MATCH_TOKEN("length", T_LENGTH);
     return T_END;
 }

+ 3 - 0
tokenizer/Token.h

@@ -65,6 +65,9 @@ typedef enum {
     T_ARROW,
     T_OPEN_SQUARE_BRACKET,
     T_CLOSE_SQUARE_BRACKET,
+    T_NEW,
+    T_DELETE,
+    T_LENGTH,
     T_END
 } Token;
 

+ 27 - 3
utils/ByteCodePrinter.c

@@ -51,6 +51,12 @@ static void btAddInt() {
     btAdd(" %10d |", value);
 }
 
+static void btAddByte() {
+    char value = 0;
+    btRead(&value, sizeof(char));
+    btAdd(" %10d |", (int)value);
+}
+
 static void btAddFloat() {
     float value = 0;
     btRead(&value, sizeof(float));
@@ -83,6 +89,14 @@ static void btPrintInt(const char* op) {
     puts(buffer);
 }
 
+static void btPrintByte(const char* op) {
+    btFillBase();
+    btAddOperation(op);
+    btAddByte();
+    btAddFiller();
+    puts(buffer);
+}
+
 static void btPrintInt2(const char* op) {
     btFillBase();
     btAddOperation(op);
@@ -104,6 +118,7 @@ static void btPrintFloat(const char* op) {
         btPrint##name(#op);                                                    \
         break;
 #define PRINT_OP(op) PRINT_OP_BASE(op, Op)
+#define PRINT_OP_BYTE(op) PRINT_OP_BASE(op, Byte)
 #define PRINT_OP_INT(op) PRINT_OP_BASE(op, Int)
 #define PRINT_OP_INT2(op) PRINT_OP_BASE(op, Int2)
 #define PRINT_NUMBER_OP(op) PRINT_OP(OP_##op##_INT) PRINT_OP(OP_##op##_FLOAT)
@@ -119,7 +134,6 @@ static void btConsumeOperation() {
         PRINT_TYPES(INT);
         PRINT_TYPES(BOOL);
         PRINT_TYPES(FLOAT);
-        PRINT_OP_INT(OP_LOAD);
         PRINT_OP(OP_NOTHING);
         PRINT_OP_INT(OP_PUSH_INT);
         PRINT_OP_BASE(OP_PUSH_FLOAT, Float);
@@ -144,6 +158,7 @@ static void btConsumeOperation() {
         PRINT_OP(OP_RIGHT_SHIFT);
         PRINT_NUMBER_OP(PRINT);
         PRINT_OP(OP_PRINT_BOOL);
+        PRINT_OP(OP_PRINT_POINTER);
         PRINT_OP_INT(OP_GOTO);
         PRINT_OP_INT(OP_IF_GOTO);
         PRINT_OP_INT(OP_PEEK_FALSE_GOTO);
@@ -154,8 +169,17 @@ static void btConsumeOperation() {
         PRINT_OP_INT(OP_DEREFERENCE_VAR);
         PRINT_OP(OP_REFERENCE);
         PRINT_OP(OP_DUPLICATE_REFERENCE);
-        PRINT_OP(OP_INT_ARRAY);
-        PRINT_OP(OP_STORE_ARRAY);
+        PRINT_OP(OP_ADD_REFERENCE);
+        PRINT_OP_INT(OP_NEW);
+        PRINT_OP(OP_DELETE);
+        PRINT_OP(OP_LENGTH);
+        PRINT_OP_INT(OP_LOAD);
+        PRINT_OP(OP_LOAD_POINTER);
+        PRINT_OP(OP_STORE_POINTER);
+        PRINT_OP(OP_EQUAL_POINTER);
+        PRINT_OP_BYTE(OP_PUSH_PRE_INT_CHANGE);
+        PRINT_OP_BYTE(OP_PUSH_POST_INT_CHANGE);
+        PRINT_OP_BYTE(OP_INT_CHANGE);
         case OP_LINE: sPrintLine(); break;
     }
 }

+ 69 - 29
vm/Arrays.c

@@ -3,6 +3,10 @@
 
 #include "vm/Arrays.h"
 
+#define MAX_ALLOCATED_BYTES (1024LL * 1024LL * 1024LL * 4LL)
+
+static long long allocatedBytes = 0;
+
 void asInit(Arrays* as) {
     as->capacity = 0;
     as->usedStart = -1;
@@ -12,15 +16,16 @@ void asInit(Arrays* as) {
 
 void asDelete(Arrays* as) {
     for(int i = 0; i < as->capacity; i++) {
+        allocatedBytes -= as->data[i].length * as->data[i].typeSize;
         free(as->data[i].data);
     }
+    allocatedBytes -= as->capacity * sizeof(Array);
     free(as->data);
 }
 
 static void aInitArray(Array* a, int previous, int next) {
     a->length = 0;
-    a->type = dtVoid();
-    a->references = 0;
+    a->typeSize = 0;
     a->next = next;
     a->previous = previous;
     a->data = NULL;
@@ -36,29 +41,52 @@ static void asInitArrays(Arrays* as, int start) {
     as->freeStart = start;
 }
 
-static void asEnsureCapacity(Arrays* as) {
+static bool asEnsureCapacity(Arrays* as) {
     if(as->freeStart != -1) {
-        return;
+        return false;
     }
-    if(as->data == NULL) {
-        as->capacity = 4;
-        as->data = malloc(sizeof(Array) * as->capacity);
-        asInitArrays(as, 0);
-    } else {
-        int start = as->capacity;
-        as->capacity *= 2;
-        as->data = realloc(as->data, sizeof(Array) * as->capacity);
-        asInitArrays(as, start);
+    int oldCapacity = as->capacity;
+    int capacity = (as->data == NULL) ? 4 : as->capacity * 2;
+    int oldBytes = sizeof(Array) * oldCapacity;
+    int bytes = sizeof(Array) * capacity;
+    if(bytes < 0 || allocatedBytes - oldBytes + bytes > MAX_ALLOCATED_BYTES) {
+        return true;
+    }
+    allocatedBytes += bytes - oldBytes;
+    as->data = realloc(as->data, bytes);
+    as->capacity = capacity;
+    asInitArrays(as, oldCapacity);
+    return false;
+}
+
+static void asPrintDebug(Arrays* as) {
+    printf("Free: %d, Used: %d\n", as->freeStart, as->usedStart);
+    for(int i = 0; i < as->capacity; i++) {
+        Array* a = as->data + i;
+        printf("%d: %s, length: %d, next: %d, previous: %d, size: %d\n", i,
+               a->data == NULL ? "null" : "valid", a->length, a->next,
+               a->previous, a->typeSize);
     }
 }
 
-int asAllocate(Arrays* as, DataType type, Structs* sts, int length) {
-    asEnsureCapacity(as);
+int asAllocate(Arrays* as, int typeSize, int length) {
+    (void)asPrintDebug;
+    if(asEnsureCapacity(as)) {
+        return -1;
+    }
+    int bytes = typeSize * length;
+    if(bytes < 0) {
+        return -2;
+    } else if(allocatedBytes + bytes > MAX_ALLOCATED_BYTES) {
+        return -1;
+    }
+    allocatedBytes += bytes;
+
     int index = as->freeStart;
     Array* array = as->data + index;
 
     as->freeStart = array->next;
-    if(array->next == -1) {
+    if(array->next != -1) {
         as->data[array->next].previous = -1;
     }
 
@@ -69,29 +97,41 @@ int asAllocate(Arrays* as, DataType type, Structs* sts, int length) {
     as->usedStart = index;
 
     array->length = length;
-    array->type = type;
-    array->data = malloc(sizeof(dtGetSize(type, sts)) * length);
+    array->typeSize = typeSize;
+    array->data = malloc(bytes);
     return index;
 }
 
 Array* asGet(Arrays* as, int p) {
-    if(p < 0 || p >= as->capacity) {
+    if(p < 0 || p >= as->capacity || as->data[p].typeSize == 0) {
         return NULL;
     }
     return as->data + p;
 }
 
-void aAddReference(Array* a) {
-    a->references++;
-}
+void asDeleteArray(Arrays* as, Array* a, int p) {
+    if(a->previous != -1) {
+        as->data[a->previous].next = a->next;
+    } else {
+        as->usedStart = a->next;
+    }
 
-void aRemoveReference(Array* a) {
-    if(--a->references > 0) {
-        return;
+    if(a->next != -1) {
+        as->data[a->next].previous = a->previous;
     }
-    printf("Please remove me");
-}
 
-void asPrintDebug(Arrays* as) {
-    (void)as;
+    if(as->freeStart != -1) {
+        a->next = as->freeStart;
+        as->data[as->freeStart].previous = p;
+    } else {
+        a->next = -1;
+    }
+    as->freeStart = p;
+
+    allocatedBytes -= a->typeSize * a->length;
+    a->previous = -1;
+    a->length = 0;
+    a->typeSize = 0;
+    free(a->data);
+    a->data = NULL;
 }

+ 3 - 6
vm/Arrays.h

@@ -7,8 +7,7 @@
 
 typedef struct {
     int length;
-    DataType type;
-    int references;
+    int typeSize;
     int next;
     int previous;
     void* data;
@@ -23,10 +22,8 @@ typedef struct {
 
 void asInit(Arrays* as);
 void asDelete(Arrays* as);
-int asAllocate(Arrays* as, DataType type, Structs* sts, int length);
+int asAllocate(Arrays* as, int typeSize, int length);
 Array* asGet(Arrays* as, int p);
-void aAddReference(Array* a);
-void aRemoveReference(Array* a);
-void asPrintDebug(Arrays* as);
+void asDeleteArray(Arrays* as, Array* a, int p);
 
 #endif

+ 12 - 3
vm/Operation.h

@@ -20,6 +20,7 @@ typedef enum Operation {
     NUMBER_OPERATION(GREATER),
     NUMBER_OPERATION(EQUAL),
     OP_EQUAL_BOOL,
+    OP_EQUAL_POINTER,
     OP_NOT,
     OP_AND,
     OP_OR,
@@ -30,6 +31,7 @@ typedef enum Operation {
     OP_LEFT_SHIFT,
     OP_RIGHT_SHIFT,
     TYPE_OPERATION(PRINT),
+    OP_PRINT_POINTER,
     OP_LINE,
     OP_GOTO,
     OP_IF_GOTO,
@@ -39,14 +41,21 @@ typedef enum Operation {
     OP_RETURN,
     TYPE_OPERATION(RETURN),
     OP_RESERVE,
-    TYPE_OPERATION(LOAD),
     OP_LOAD,
+    TYPE_OPERATION(LOAD),
     TYPE_OPERATION(STORE),
     OP_DEREFERENCE_VAR,
     OP_REFERENCE,
     OP_DUPLICATE_REFERENCE,
-    OP_INT_ARRAY,
-    OP_STORE_ARRAY
+    OP_ADD_REFERENCE,
+    OP_NEW,
+    OP_DELETE,
+    OP_LENGTH,
+    OP_LOAD_POINTER,
+    OP_STORE_POINTER,
+    OP_PUSH_PRE_INT_CHANGE,
+    OP_PUSH_POST_INT_CHANGE,
+    OP_INT_CHANGE
 } Operation;
 
 #endif

+ 209 - 63
vm/Script.c

@@ -26,9 +26,14 @@ static void sBoolPrinter(bool b) {
     puts(b ? "true" : "false");
 }
 
+static void sPointerPrinter(Pointer* b) {
+    printf("(%d, %d)\n", b->array, b->offset);
+}
+
 static IntPrinter intPrinter = sIntPrinter;
 static FloatPrinter floatPrinter = sFloatPrinter;
 static BoolPrinter boolPrinter = sBoolPrinter;
+static PointerPrinter pointerPrinter = sPointerPrinter;
 
 static bool sRead(Script* sc, void* buffer, int length) {
     if(sc->readIndex + length > sc->code->length) {
@@ -143,6 +148,21 @@ READ_POP_PUSH(int, Int)
 READ_POP_PUSH(float, Float)
 POP_PUSH(bool, Bool)
 
+static bool sPopPointer(Script* sc, Pointer* value) {
+    return sPop(sc, value, sizeof(Pointer));
+}
+
+static bool sPushPointer(Script* sc, Pointer* value) {
+    return sPush(sc, value, sizeof(Pointer));
+}
+
+static void sPrintPointer(Script* sc) {
+    Pointer p;
+    if(sPopPointer(sc, &p)) {
+        pointerPrinter(&p);
+    }
+}
+
 #define PRINT(type, Type, printer)                                             \
     {                                                                          \
         type value;                                                            \
@@ -170,26 +190,26 @@ static void sReserveBytes(Script* sc) {
     }
 }
 
-static bool sCheckAddress(Script* sc, int address, int length) {
-    if(address < 0 || address + length > sc->stackIndex) {
-        sError(sc, "address is out of stack bounds");
-        return false;
-    }
-    return true;
-}
-
-static void sStore(Script* sc, int length) {
-    int address = -1;
-    int index = sc->stackIndex - sizeof(int) - length;
-    if(index < 0) {
-        sError(sc, "stack underflow");
-        return;
+static void* sCheckAddress(Script* sc, Pointer* p, int length) {
+    if(p->array >= 0) {
+        Array* a = asGet(&sc->arrays, p->array);
+        if(a == NULL) {
+            sError(sc, "invalid heap pointer");
+            return NULL;
+        } else if(p->offset < 0 || p->offset >= a->length) {
+            sError(sc, "address %d is out of array bounds", p->offset);
+            return NULL;
+        } else if(length != a->typeSize) {
+            sError(sc, "sizes do not match: %d != %d", length, a->typeSize);
+            return NULL;
+        }
+        return ((char*)a->data) + p->offset * a->typeSize;
     }
-    memcpy(&address, sc->stack + index, sizeof(int));
-    if(sCheckAddress(sc, address, length)) {
-        sPop(sc, sc->stack + address, length);
-        sc->stackIndex -= sizeof(int);
+    if(p->offset < 0 || p->offset + length > sc->stackIndex) {
+        sError(sc, "address %d is out of stack bounds", p->offset);
+        return NULL;
     }
+    return sc->stack + p->offset;
 }
 
 static void sNot(Script* sc) {
@@ -221,9 +241,11 @@ static void sGoSub(Script* sc) {
     int gotoIndex;
     int offset;
     if(sReadInt(sc, &gotoIndex) && sReadInt(sc, &offset)) {
-        int address = sc->stackIndex - offset - sizeof(int);
-        if(sCheckAddress(sc, address, sizeof(int))) {
-            memcpy(sc->stack + address, &sc->readIndex, sizeof(int));
+        Pointer p = {.array = -1,
+                     .offset = sc->stackIndex - offset - sizeof(int)};
+        void* dest = sCheckAddress(sc, &p, sizeof(int));
+        if(dest != NULL) {
+            memcpy(dest, &sc->readIndex, sizeof(int));
             sc->readIndex = gotoIndex;
         }
     }
@@ -274,44 +296,174 @@ static void sPeekTrueGoTo(Script* sc) {
     }
 }
 
-static void sIntArray(Script* sc) {
-    (void)sc;
+static void sNewArray(Script* sc) {
+    int length = 0;
+    int size = 0;
+    if(sReadInt(sc, &size) && sPopInt(sc, &length)) {
+        Pointer p = {.array = asAllocate(&sc->arrays, size, length),
+                     .offset = 0};
+        if(p.array == -1) {
+            sError(sc, "out of memory");
+        } else if(p.array == -2) {
+            sError(sc, "bad allocation");
+        } else {
+            sPushPointer(sc, &p);
+        }
+    }
+}
+
+static void sDeleteArray(Script* sc) {
+    Pointer p;
+    if(sPopPointer(sc, &p)) {
+        if(p.offset != 0) {
+            sError(sc, "delete of array with offset: %d", p.offset);
+            return;
+        }
+        Array* a = asGet(&sc->arrays, p.array);
+        if(a == NULL) {
+            sError(sc, "delete of invalid array");
+            return;
+        }
+        asDeleteArray(&sc->arrays, a, p.array);
+    }
+}
+
+static void sLength(Script* sc) {
+    Pointer p;
+    if(sPopPointer(sc, &p)) {
+        if(p.array == -1) {
+            sPushInt(sc, 1);
+            return;
+        }
+        Array* a = asGet(&sc->arrays, p.array);
+        if(a == NULL) {
+            sError(sc, "invalid heap pointer");
+            return;
+        }
+        sPushInt(sc, a->length);
+    }
 }
 
-static void sVarRef(Script* sc) {
+static void sDereference(Script* sc) {
     int address = 0;
     if(sReadInt(sc, &address)) {
-        sPushInt(sc, address + sc->stackVarIndex);
+        Pointer p = {.array = -1, .offset = address + sc->stackVarIndex};
+        sPushPointer(sc, &p);
     }
 }
 
 static void sReference(Script* sc) {
-    int reference = 0;
-    if(sPopInt(sc, &reference) && sCheckAddress(sc, reference, sizeof(int))) {
-        sPush(sc, sc->stack + reference, sizeof(int));
+    Pointer p;
+    if(sPopPointer(sc, &p)) {
+        void* src = sCheckAddress(sc, &p, sizeof(Pointer));
+        if(src != NULL) {
+            memcpy(&p, src, sizeof(Pointer));
+            sPushPointer(sc, &p);
+        }
     }
 }
 
 static void sDuplicateReference(Script* sc) {
-    int reference = 0;
-    if(sPeek(sc, &reference, sizeof(int))) {
-        sPushInt(sc, reference);
+    Pointer p;
+    if(sPeek(sc, &p, sizeof(Pointer))) {
+        sPushPointer(sc, &p);
     }
 }
 
-static void sRefLoad(Script* sc) {
+static void sAddReference(Script* sc) {
+    int add = 0;
+    Pointer p;
+    if(sPopInt(sc, &add) && sPopPointer(sc, &p)) {
+        p.offset += add;
+        sPushPointer(sc, &p);
+    }
+}
+
+static void sLoadSize(Script* sc) {
     int size = 0;
-    int address = 0;
-    if(sReadInt(sc, &size) && sPopInt(sc, &address) &&
-       sCheckAddress(sc, address, size)) {
-        sPush(sc, sc->stack + address, size);
+    Pointer p;
+    if(sReadInt(sc, &size) && sPopPointer(sc, &p)) {
+        void* src = sCheckAddress(sc, &p, size);
+        if(src != NULL) {
+            sPush(sc, src, size);
+        }
+    }
+}
+
+static void sStore(Script* sc, int length) {
+    int index = sc->stackIndex - sizeof(Pointer) - length;
+    if(index < 0) {
+        sError(sc, "stack underflow");
+        return;
+    }
+    Pointer p;
+    memcpy(&p, sc->stack + index, sizeof(Pointer));
+    void* dest = sCheckAddress(sc, &p, length);
+    if(dest != NULL) {
+        sPop(sc, dest, length);
+        sc->stackIndex -= sizeof(Pointer);
     }
 }
 
 static void sLoad(Script* sc, int length) {
-    int address = 0;
-    if(sPopInt(sc, &address) && sCheckAddress(sc, address, length)) {
-        sPush(sc, sc->stack + address, length);
+    Pointer p;
+    if(sPopPointer(sc, &p)) {
+        void* src = sCheckAddress(sc, &p, length);
+        if(src != NULL) {
+            sPush(sc, src, length);
+        }
+    }
+}
+
+static void sEqualPointer(Script* sc) {
+    Pointer a;
+    Pointer b;
+    if(sPopPointer(sc, &a) && sPopPointer(sc, &b)) {
+        sPushBool(sc, a.array == b.array && a.offset == b.offset);
+    }
+}
+
+static void sPushPreIntChange(Script* sc) {
+    char c = 0;
+    Pointer p;
+    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
+        void* data = sCheckAddress(sc, &p, sizeof(int));
+        if(data != NULL) {
+            int current = 0;
+            memcpy(&current, data, sizeof(int));
+            current += c;
+            sPushInt(sc, current);
+            memcpy(data, &current, sizeof(int));
+        }
+    }
+}
+
+static void sPushPostIntChange(Script* sc) {
+    char c = 0;
+    Pointer p;
+    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
+        void* data = sCheckAddress(sc, &p, sizeof(int));
+        if(data != NULL) {
+            int current = 0;
+            memcpy(&current, data, sizeof(int));
+            sPushInt(sc, current);
+            current += c;
+            memcpy(data, &current, sizeof(int));
+        }
+    }
+}
+
+static void sIntChange(Script* sc) {
+    char c = 0;
+    Pointer p;
+    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
+        void* data = sCheckAddress(sc, &p, sizeof(int));
+        if(data != NULL) {
+            int current = 0;
+            memcpy(&current, data, sizeof(int));
+            current += c;
+            memcpy(data, &current, sizeof(int));
+        }
     }
 }
 
@@ -369,14 +521,22 @@ static void sConsumeInstruction(Script* sc) {
         case OP_GOSUB: sGoSub(sc); break;
         case OP_RETURN: sReturn(sc); break;
         case OP_RESERVE: sReserveBytes(sc); break;
-        case OP_DEREFERENCE_VAR: sVarRef(sc); break;
+        case OP_DEREFERENCE_VAR: sDereference(sc); break;
         case OP_REFERENCE: sReference(sc); break;
         case OP_DUPLICATE_REFERENCE: sDuplicateReference(sc); break;
-        case OP_LOAD: sRefLoad(sc); break;
-        case OP_INT_ARRAY: sIntArray(sc); break;
-        case OP_STORE_ARRAY: sStore(sc, sizeof(int)); break;
+        case OP_ADD_REFERENCE: sAddReference(sc); break;
+        case OP_LOAD: sLoadSize(sc); break;
+        case OP_NEW: sNewArray(sc); break;
+        case OP_DELETE: sDeleteArray(sc); break;
+        case OP_LENGTH: sLength(sc); break;
+        case OP_LOAD_POINTER: sLoad(sc, sizeof(Pointer)); break;
+        case OP_STORE_POINTER: sStore(sc, sizeof(Pointer)); break;
+        case OP_PRINT_POINTER: sPrintPointer(sc); break;
+        case OP_EQUAL_POINTER: sEqualPointer(sc); break;
+        case OP_PUSH_PRE_INT_CHANGE: sPushPreIntChange(sc); break;
+        case OP_PUSH_POST_INT_CHANGE: sPushPostIntChange(sc); break;
+        case OP_INT_CHANGE: sIntChange(sc); break;
     }
-    // sCollectGarbage(sc);
 }
 
 static bool sHasData(Script* sc) {
@@ -391,13 +551,13 @@ Script* sInit(ByteCode* code) {
     sc->stackIndex = 0;
     sc->stackVarIndex = 0;
     sc->line = 0;
-    // aInit(&sc->allocator);
+    asInit(&sc->arrays);
     return sc;
 }
 
 void sDelete(Script* sc) {
     bcDelete(sc->code);
-    // aDelete(&sc->allocator);
+    asDelete(&sc->arrays);
     free(sc);
 }
 
@@ -425,20 +585,6 @@ void sSetBoolPrinter(BoolPrinter p) {
     boolPrinter = p;
 }
 
-/*static void sMark(Script* sc, Object* o) {
-    if(o->type == OT_ARRAY) {
-        Array* a = sc->allocator.data + o->as.intValue;
-        a->marked = true;
-        for(int i = 0; i < a->length; i++) {
-            sMark(sc, a->data + i);
-        }
-    }
-}
-
-void sCollectGarbage(Script* sc) {
-    aClearMarker(&sc->allocator);
-    for(int i = 0; i < sc->stackIndex; i++) {
-        sMark(sc, sc->stack + i);
-    }
-    aRemoveUnmarked(&sc->allocator);
-}*/
+void sSetPointerPrinter(PointerPrinter p) {
+    pointerPrinter = p;
+}

+ 3 - 1
vm/Script.h

@@ -17,7 +17,7 @@ typedef struct {
     int stackIndex;
     int stackVarIndex;
     int line;
-    // Allocator allocator;
+    Arrays arrays;
 } Script;
 
 Script* sInit(ByteCode* code);
@@ -31,5 +31,7 @@ typedef void (*FloatPrinter)(float);
 void sSetFloatPrinter(FloatPrinter p);
 typedef void (*BoolPrinter)(bool);
 void sSetBoolPrinter(BoolPrinter p);
+typedef void (*PointerPrinter)(Pointer*);
+void sSetPointerPrinter(PointerPrinter p);
 
 #endif