Browse Source

base for arrays

Kajetan Johannes Hammerle 3 years ago
parent
commit
b6b83dfecd
18 changed files with 254 additions and 146 deletions
  1. 30 1
      Compiler.c
  2. 49 5
      DataType.c
  3. 5 0
      DataType.h
  4. 1 1
      meson.build
  5. 0 9
      old_tests/arrays/alloc
  6. 0 5
      old_tests/arrays/alloc.out
  7. 11 0
      tests/arrays/alloc
  8. 1 0
      tests/arrays/alloc.out
  9. 0 2
      tokenizer/Token.c
  10. 0 1
      tokenizer/Token.h
  11. 2 0
      utils/ByteCodePrinter.c
  12. 0 92
      vm/Allocator.c
  13. 0 28
      vm/Allocator.h
  14. 113 0
      vm/Arrays.c
  15. 32 0
      vm/Arrays.h
  16. 3 1
      vm/Operation.h
  17. 6 0
      vm/Script.c
  18. 1 1
      vm/Script.h

+ 30 - 1
Compiler.c

@@ -221,7 +221,12 @@ static void cStoreVariable(Variable* v, DataType dt, const char* name) {
         case DT_INT: cAddOperation(OP_STORE_INT); break;
         case DT_BOOL: cAddOperation(OP_STORE_BOOL); break;
         case DT_FLOAT: cAddOperation(OP_STORE_FLOAT); break;
-        default: cError("cannot store type %s", dtGetName(v->type));
+        default:
+            if(dtIsArray(v->type)) {
+                cAddOperation(OP_STORE_ARRAY);
+            } else {
+                cError("cannot store type %s", dtGetName(v->type));
+            }
     }
     cAddInt(v->address);
 }
@@ -269,6 +274,17 @@ static DataType cBracketPrimary() {
     return result;
 }
 
+static DataType cAllocArray(DataType dt, Operation op) {
+    cConsumeToken(T_OPEN_SQUARE_BRACKET);
+    DataType index = cExpression();
+    if(index != DT_INT) {
+        cError("array size must be an int");
+    }
+    cConsumeToken(T_CLOSE_SQUARE_BRACKET);
+    cAddOperation(op);
+    return dtArray(dt, 1);
+}
+
 static DataType cPrimary() {
     Token t = cReadTokenAndLine();
     switch(t) {
@@ -278,6 +294,7 @@ static DataType cPrimary() {
         case T_FALSE: cAddOperation(OP_PUSH_FALSE); return DT_BOOL;
         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;
     }
 }
@@ -670,7 +687,19 @@ static void cWhile() {
     cConsumeBreaks(breakStart, code->length);
 }
 
+static DataType cDimension(DataType dt) {
+    int dimension = 0;
+    while(cConsumeTokenIf(T_MUL)) {
+        dimension++;
+    }
+    if(dimension > 0) {
+        dt = dtArray(dt, dimension);
+    }
+    return dt;
+}
+
 static void cDeclare(DataType dt) {
+    dt = cDimension(dt);
     cConsumeToken(T_LITERAL);
     const char* var = cReadString();
     Variable* v = vSearchScope(&vars, var);

+ 49 - 5
DataType.c

@@ -1,14 +1,46 @@
-#include <stdbool.h>
-
 #include "DataType.h"
 
-const char* dtGetName(DataType dt) {
+#define ARRAY_NAME 20
+#define ARRAY_FACTOR 10
+
+static char arrayName[ARRAY_NAME];
+
+static const char* dtGetBaseName(DataType dt) {
     switch(dt) {
         case DT_INT: return "int";
         case DT_FLOAT: return "float";
         case DT_BOOL: return "bool";
-        default: return "unknown";
+        default: return "";
+    }
+}
+
+static const char* dtGetArrayName(DataType dt) {
+    int dimension = dt % ARRAY_FACTOR;
+    DataType real = (dt / ARRAY_FACTOR) - 1;
+    const char* name = dtGetBaseName(real);
+    if(name[0] == '\0' || dimension <= 0 || dimension > dtMaxDimensions()) {
+        return "unknown";
+    }
+    int index = 0;
+    while(index < (ARRAY_NAME - 1) && name[index] != '\0') {
+        arrayName[index] = name[index];
+        index++;
     }
+    while(index < (ARRAY_NAME - 1) && dimension > 0) {
+        arrayName[index] = '*';
+        index++;
+        dimension--;
+    }
+    arrayName[index] = '\0';
+    return arrayName;
+}
+
+const char* dtGetName(DataType dt) {
+    const char* name = dtGetBaseName(dt);
+    if(name[0] == '\0') {
+        return dtGetArrayName(dt);
+    }
+    return name;
 }
 
 int dtGetSize(DataType dt) {
@@ -16,6 +48,18 @@ int dtGetSize(DataType dt) {
         case DT_INT: return sizeof(int);
         case DT_FLOAT: return sizeof(float);
         case DT_BOOL: return sizeof(bool);
-        default: return 0;
+        default: return sizeof(int);
     }
+}
+
+DataType dtArray(DataType dt, int dimensions) {
+    return (dt + 1) * ARRAY_FACTOR + dimensions;
+}
+
+int dtMaxDimensions() {
+    return ARRAY_FACTOR - 1;
+}
+
+bool dtIsArray(DataType dt) {
+    return dt > ARRAY_FACTOR;
 }

+ 5 - 0
DataType.h

@@ -1,9 +1,14 @@
 #ifndef DATATYPE_H
 #define DATATYPE_H
 
+#include <stdbool.h>
+
 typedef enum { DT_INT, DT_FLOAT, DT_BOOL, DT_VOID } DataType;
 
 const char* dtGetName(DataType dt);
 int dtGetSize(DataType dt);
+DataType dtArray(DataType dt, int dimensions);
+int dtMaxDimensions();
+bool dtIsArray(DataType dt);
 
 #endif

+ 1 - 1
meson.build

@@ -14,7 +14,7 @@ src = [
     'Test.c', 
     'vm/ByteCode.c',
     'vm/Script.c', 
-    'vm/Allocator.c'
+    'vm/Arrays.c'
 ]
 
 executable('lonely_tiger', 

+ 0 - 9
old_tests/arrays/alloc

@@ -1,9 +0,0 @@
-a = array[4];
-print a.length;
-a[0] = 5;
-a[1] = true;
-a[2] = "Hi";
-print a[0];
-print a[1];
-print a[2];
-print a[3];

+ 0 - 5
old_tests/arrays/alloc.out

@@ -1,5 +0,0 @@
-4
-5
-true
-Hi
-null

+ 11 - 0
tests/arrays/alloc

@@ -0,0 +1,11 @@
+void main() {
+    int* a = int[4];
+    /*print a.length;
+    a[0] = 5;
+    a[1] = true;
+    a[2] = "Hi";
+    print a[0];
+    print a[1];
+    print a[2];
+    print a[3];*/
+}

+ 1 - 0
tests/arrays/alloc.out

@@ -0,0 +1 @@
+4

+ 0 - 2
tokenizer/Token.c

@@ -63,7 +63,6 @@ const char* tGetName(Token token) {
         case T_CLOSE_BRACKET: return ")";
         case T_OPEN_CURVED_BRACKET: return "{";
         case T_CLOSE_CURVED_BRACKET: return "}";
-        case T_ARRAY: return "array";
         case T_POINT: return ".";
         case T_OPEN_SQUARE_BRACKET: return "[";
         case T_CLOSE_SQUARE_BRACKET: return "]";
@@ -89,7 +88,6 @@ Token tFromName(const char* name) {
     MATCH_TOKEN("for", T_FOR);
     MATCH_TOKEN("break", T_BREAK);
     MATCH_TOKEN("continue", T_CONTINUE);
-    MATCH_TOKEN("array", T_ARRAY);
     MATCH_TOKEN("int", T_INT);
     MATCH_TOKEN("void", T_VOID);
     MATCH_TOKEN("bool", T_BOOL);

+ 0 - 1
tokenizer/Token.h

@@ -60,7 +60,6 @@ typedef enum {
     T_CLOSE_BRACKET,
     T_OPEN_CURVED_BRACKET,
     T_CLOSE_CURVED_BRACKET,
-    T_ARRAY,
     T_POINT,
     T_OPEN_SQUARE_BRACKET,
     T_CLOSE_SQUARE_BRACKET,

+ 2 - 0
utils/ByteCodePrinter.c

@@ -150,6 +150,8 @@ static void btConsumeOperation() {
         PRINT_OP_INT2(OP_GOSUB);
         PRINT_OP_INT(OP_RETURN);
         PRINT_OP_INT2(OP_RESERVE);
+        PRINT_OP(OP_INT_ARRAY);
+        PRINT_OP_INT(OP_STORE_ARRAY);
         case OP_LINE: sPrintLine(); break;
     }
 }

+ 0 - 92
vm/Allocator.c

@@ -1,92 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "vm/Allocator.h"
-
-/*void aInit(Allocator* a) {
-    a->capacity = 0;
-    a->usedStart = -1;
-    a->freeStart = -1;
-    a->data = NULL;
-}
-
-void aDelete(Allocator* a) {
-    for(int i = a->usedStart; i != -1; i = a->data[i].next) {
-        printf("end Dealloc %d\n", a->data[i].length);
-        free(a->data[i].data);
-    }
-    free(a->data);
-}
-
-static void aInitArray(Array* a, int next) {
-    a->length = 0;
-    a->next = next;
-    a->marked = false;
-    a->data = NULL;
-}
-
-static void aInitArrays(Allocator* a, int start) {
-    for(int i = start; i < a->capacity - 1; i++) {
-        aInitArray(a->data + i, i + 1);
-    }
-    aInitArray(a->data + (a->capacity - 1), -1);
-    a->freeStart = start;
-}
-
-int aAllocate(Allocator* a, int length) {
-    if(a->freeStart == -1) {
-        if(a->data == NULL) {
-            a->capacity = 4;
-            a->data = malloc(sizeof(Array) * a->capacity);
-            aInitArrays(a, 0);
-        } else {
-            int start = a->capacity;
-            a->capacity *= 2;
-            a->data = realloc(a->data, sizeof(Array) * a->capacity);
-            aInitArrays(a, start);
-        }
-    }
-    int index = a->freeStart;
-    Array* array = a->data + index;
-    a->freeStart = array->next;
-
-    array->length = length;
-    array->next = a->usedStart;
-    a->usedStart = index;
-    array->data = malloc(sizeof(Object) * length);
-    for(int i = 0; i < length; i++) {
-        array->data[i].type = OT_NULL;
-    }
-    return index;
-}
-
-void aClearMarker(Allocator* a) {
-    for(int i = a->usedStart; i != -1; i = a->data[i].next) {
-        a->data[i].marked = false;
-    }
-}
-
-void aRemoveUnmarked(Allocator* a) {
-    int prev = -1;
-    int i = a->usedStart;
-    while(i != -1) {
-        int next = a->data[i].next;
-        if(!a->data[i].marked) {
-            free(a->data[i].data);
-
-            if(prev == -1) {
-                a->usedStart = next;
-            } else {
-                a->data[prev].next = next;
-            }
-            a->data[i].next = a->freeStart;
-            a->freeStart = i;
-
-            a->data[i].length = 0;
-            a->data[i].data = NULL;
-        } else {
-            prev = i;
-        }
-        i = next;
-    }
-}*/

+ 0 - 28
vm/Allocator.h

@@ -1,28 +0,0 @@
-#ifndef ALLOCATOR_H
-#define ALLOCATOR_H
-
-#include <stdbool.h>
-
-typedef struct {
-    int length;
-    int next;
-    bool marked;
-    // Object* data;
-} Array;
-
-typedef struct {
-    int capacity;
-    int usedStart;
-    int freeStart;
-    Array* data;
-} Allocator;
-
-void aInit(Allocator* a);
-void aDelete(Allocator* a);
-
-int aAllocate(Allocator* a, int length);
-
-void aClearMarker(Allocator* a);
-void aRemoveUnmarked(Allocator* a);
-
-#endif

+ 113 - 0
vm/Arrays.c

@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "vm/Arrays.h"
+
+/*typedef struct {
+    int length;
+    DataType type;
+    int references;
+    int next;
+    int previous;
+    void* data;
+} Array;
+
+typedef struct {
+    int capacity;
+    int usedStart;
+    int freeStart;
+    Array* data;
+} Arrays;*/
+
+void asInit(Arrays* as) {
+    as->capacity = 0;
+    as->usedStart = -1;
+    as->freeStart = -1;
+    as->data = NULL;
+}
+
+void asDelete(Arrays* as) {
+    for(int i = 0; i < as->capacity; i++) {
+        free(as->data[i].data);
+    }
+    free(as->data);
+}
+
+static void aInitArray(Array* a, int previous, int next) {
+    a->length = 0;
+    a->type = DT_VOID;
+    a->references = 0;
+    a->next = next;
+    a->previous = previous;
+    a->data = NULL;
+}
+
+static void asInitArrays(Arrays* as, int start) {
+    int end = as->capacity - 1;
+    aInitArray(as->data + start, -1, start + 1);
+    for(int i = start + 1; i < end; i++) {
+        aInitArray(as->data + i, i - 1, i + 1);
+    }
+    aInitArray(as->data + end, end - 1, -1);
+    as->freeStart = start;
+}
+
+static void asEnsureCapacity(Arrays* as) {
+    if(as->freeStart != -1) {
+        return;
+    }
+    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 asAllocate(Arrays* as, DataType type, int length) {
+    asEnsureCapacity(as);
+    int index = as->freeStart;
+    Array* array = as->data + index;
+
+    as->freeStart = array->next;
+    if(array->next == -1) {
+        as->data[array->next].previous = -1;
+    }
+
+    array->next = as->usedStart;
+    if(as->usedStart != -1) {
+        as->data[as->usedStart].previous = index;
+    }
+    as->usedStart = index;
+
+    array->length = length;
+    array->type = type;
+    array->data = malloc(sizeof(dtGetSize(type)) * length);
+    return index;
+}
+
+Array* asGet(Arrays* as, int p) {
+    if(p < 0 || p >= as->capacity) {
+        return NULL;
+    }
+    return as->data + p;
+}
+
+void aAddReference(Array* a) {
+    a->references++;
+}
+
+void aRemoveReference(Array* a) {
+    if(--a->references > 0) {
+        return;
+    }
+    printf("Please remove me");
+}
+
+void asPrintDebug(Arrays* as) {
+    (void)as;
+}

+ 32 - 0
vm/Arrays.h

@@ -0,0 +1,32 @@
+#ifndef ARRAYS_H
+#define ARRAYS_H
+
+#include <stdbool.h>
+
+#include "DataType.h"
+
+typedef struct {
+    int length;
+    DataType type;
+    int references;
+    int next;
+    int previous;
+    void* data;
+} Array;
+
+typedef struct {
+    int capacity;
+    int usedStart;
+    int freeStart;
+    Array* data;
+} Arrays;
+
+void asInit(Arrays* as);
+void asDelete(Arrays* as);
+int asAllocate(Arrays* as, DataType type, int length);
+Array* asGet(Arrays* as, int p);
+void aAddReference(Array* a);
+void aRemoveReference(Array* a);
+void asPrintDebug(Arrays* as);
+
+#endif

+ 3 - 1
vm/Operation.h

@@ -40,7 +40,9 @@ typedef enum Operation {
     TYPE_OPERATION(RETURN),
     OP_RESERVE,
     TYPE_OPERATION(LOAD),
-    TYPE_OPERATION(STORE)
+    TYPE_OPERATION(STORE),
+    OP_INT_ARRAY,
+    OP_STORE_ARRAY
 } Operation;
 
 #endif

+ 6 - 0
vm/Script.c

@@ -281,6 +281,10 @@ static void sPeekTrueGoTo(Script* sc) {
     }
 }
 
+static void sIntArray(Script* sc) {
+    (void)sc;
+}
+
 #define CASE_NUMBER_OP(name, op)                                               \
     case OP_##name##_INT: NUMBER_OP(int, Int, op); break;                      \
     case OP_##name##_FLOAT:                                                    \
@@ -335,6 +339,8 @@ 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_INT_ARRAY: sIntArray(sc); break;
+        case OP_STORE_ARRAY: sStore(sc, sizeof(int)); break;
     }
     // sCollectGarbage(sc);
 }

+ 1 - 1
vm/Script.h

@@ -3,7 +3,7 @@
 
 #include <stdbool.h>
 
-#include "vm/Allocator.h"
+#include "vm/Arrays.h"
 #include "vm/ByteCode.h"
 
 #define SCRIPT_STACK_SIZE 1000