瀏覽代碼

base for structs

Kajetan Johannes Hammerle 3 年之前
父節點
當前提交
ac4a7f6b5a
共有 15 個文件被更改,包括 175 次插入7 次删除
  1. 57 0
      Compiler.c
  2. 9 1
      DataType.c
  3. 1 0
      DataType.h
  4. 1 0
      meson.build
  5. 2 2
      tests/arrays/alloc
  6. 0 1
      tests/arrays/alloc.out
  7. 15 0
      tests/struct/alloc
  8. 3 0
      tests/struct/alloc.out
  9. 2 0
      tokenizer/Token.c
  10. 1 0
      tokenizer/Token.h
  11. 1 1
      tokenizer/Tokenizer.c
  12. 47 0
      utils/Structs.c
  13. 31 0
      utils/Structs.h
  14. 4 1
      utils/Variables.c
  15. 1 1
      utils/Variables.h

+ 57 - 0
Compiler.c

@@ -1,12 +1,14 @@
 #include <setjmp.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "Compiler.h"
 #include "DataType.h"
 #include "tokenizer/Tokenizer.h"
 #include "utils/Functions.h"
+#include "utils/Structs.h"
 #include "utils/Variables.h"
 #include "vm/Operation.h"
 
@@ -24,6 +26,7 @@ static int16 line = 1;
 static Variables vars;
 static Functions functions;
 static Functions functionQueue;
+static Structs structs;
 
 static int returns[RETURN_BUFFER];
 static int returnIndex = 0;
@@ -537,6 +540,26 @@ static void cAddPostLineChange(Variable* v, int change, const char* name) {
     cAddInt(v->address);
 }
 
+static void cDeclareStruct(Struct* st) {
+    cConsumeToken(T_LITERAL);
+    const char* var = cReadString();
+    Variable* v = vSearchScope(&vars, var);
+    if(v != NULL) {
+        cDeclared(var);
+    }
+    vAdd(&vars, var, dtStruct(st->id));
+    int varLength = strlen(var);
+    for(int i = 0; i < st->amount; i++) {
+        int length = strlen(st->vars[i].name);
+        char* fullName = malloc(varLength + length + 2);
+        memcpy(fullName, var, varLength);
+        fullName[varLength] = '.';
+        memcpy(fullName + varLength + 1, st->vars[i].name, length + 1);
+        vAdd(&vars, fullName, st->vars[i].type);
+        free(fullName);
+    }
+}
+
 static void cLineLiteral() {
     const char* literal = cReadString();
     if(cConsumeTokenIf(T_OPEN_BRACKET)) {
@@ -546,6 +569,11 @@ static void cLineLiteral() {
         }
         return;
     }
+    Struct* st = stsSearch(&structs, literal);
+    if(st != NULL) {
+        cDeclareStruct(st);
+        return;
+    }
     Variable* v = vSearch(&vars, literal);
     if(v == NULL) {
         cNotDeclared(literal);
@@ -926,12 +954,39 @@ static void cFunction(DataType rType) {
     cSetInt(end, code->length);
 }
 
+static void cStruct() {
+    cConsumeToken(T_LITERAL);
+    const char* name = cReadString();
+    if(stsSearch(&structs, name) != NULL) {
+        cError("struct registered twice");
+    }
+    Struct* st = stsAdd(&structs, name);
+    cConsumeToken(T_OPEN_CURVED_BRACKET);
+    while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
+        Token t = cReadTokenAndLine();
+        DataType dt = DT_VOID;
+        switch(t) {
+            case T_INT: dt = DT_INT; break;
+            case T_BOOL: dt = DT_BOOL; break;
+            case T_FLOAT: dt = DT_FLOAT; break;
+            default: cUnexpectedToken(t);
+        }
+        dt = cDimension(dt);
+        cConsumeToken(T_LITERAL);
+        const char* name = cReadString();
+        stAddVariable(st, name, dt);
+        cConsumeToken(T_SEMICOLON);
+    }
+    cConsumeToken(T_SEMICOLON);
+}
+
 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_STRUCT: cStruct(); break;
         default: cUnexpectedToken(t);
     }
 }
@@ -979,10 +1034,12 @@ static void cAllocAndCompile() {
     vInit(&vars);
     fsInit(&functions);
     fsInit(&functionQueue);
+    stsInit(&structs);
     if(!setjmp(errorJump)) {
         cForEachLine();
         cLinkQueuedFunctions();
     }
+    stsDelete(&structs);
     fsDelete(&functionQueue);
     fsDelete(&functions);
     vDelete(&vars);

+ 9 - 1
DataType.c

@@ -48,7 +48,11 @@ int dtGetSize(DataType dt) {
         case DT_INT: return sizeof(int);
         case DT_FLOAT: return sizeof(float);
         case DT_BOOL: return sizeof(bool);
-        default: return sizeof(int);
+        default:
+            if(dt >= 1000) {
+                return 0;
+            }
+            return sizeof(int);
     }
 }
 
@@ -56,6 +60,10 @@ DataType dtArray(DataType dt, int dimensions) {
     return (dt + 1) * ARRAY_FACTOR + dimensions;
 }
 
+DataType dtStruct(int id) {
+    return 1000 + id;
+}
+
 int dtMaxDimensions() {
     return ARRAY_FACTOR - 1;
 }

+ 1 - 0
DataType.h

@@ -8,6 +8,7 @@ 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);
+DataType dtStruct(int id);
 int dtMaxDimensions();
 bool dtIsArray(DataType dt);
 

+ 1 - 0
meson.build

@@ -9,6 +9,7 @@ src = [
     'utils/Variables.c',
     'utils/Functions.c',
     'utils/ByteCodePrinter.c',
+    'utils/Structs.c',
     'Compiler.c', 
     'DataType.c', 
     'Test.c', 

+ 2 - 2
tests/arrays/alloc

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

+ 0 - 1
tests/arrays/alloc.out

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

+ 15 - 0
tests/struct/alloc

@@ -0,0 +1,15 @@
+struct A {
+    float f;
+    int i;
+    bool b;
+};
+
+void main() {
+    A a;
+    a.f = 5.0;
+    a.i = 7;
+    a.b = true;
+    print a.f;
+    print a.i;
+    print a.b;
+}

+ 3 - 0
tests/struct/alloc.out

@@ -0,0 +1,3 @@
+5.00
+7
+true

+ 2 - 0
tokenizer/Token.c

@@ -57,6 +57,7 @@ const char* tGetName(Token token) {
         case T_BREAK: return "break";
         case T_CONTINUE: return "continue";
         case T_RETURN: return "return";
+        case T_STRUCT: return "struct";
         case T_COMMA: return ",";
         case T_SEMICOLON: return ";";
         case T_OPEN_BRACKET: return "(";
@@ -92,5 +93,6 @@ Token tFromName(const char* name) {
     MATCH_TOKEN("void", T_VOID);
     MATCH_TOKEN("bool", T_BOOL);
     MATCH_TOKEN("float", T_FLOAT);
+    MATCH_TOKEN("struct", T_STRUCT);
     return T_END;
 }

+ 1 - 0
tokenizer/Token.h

@@ -54,6 +54,7 @@ typedef enum {
     T_BREAK,
     T_CONTINUE,
     T_RETURN,
+    T_STRUCT,
     T_COMMA,
     T_SEMICOLON,
     T_OPEN_BRACKET,

+ 1 - 1
tokenizer/Tokenizer.c

@@ -52,7 +52,7 @@ static bool tParseLiteral(int c) {
     int index = 1;
     char buffer[64];
     buffer[0] = c;
-    while(isLetter(fPeek())) {
+    while(isLetter(fPeek()) || fPeek() == '.') {
         if(index >= 63) {
             tError("literal is too long");
             return false;

+ 47 - 0
utils/Structs.c

@@ -0,0 +1,47 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils/Structs.h"
+
+void stAddVariable(Struct* st, const char* name, DataType type) {
+    int index = st->amount;
+    st->amount++;
+    st->vars = realloc(st->vars, sizeof(StructVariable) * st->amount);
+    st->vars[index].name = name;
+    st->vars[index].type = type;
+}
+
+void stsInit(Structs* sts) {
+    sts->capacity = 4;
+    sts->entries = 0;
+    sts->data = malloc(sizeof(Struct) * sts->capacity);
+}
+
+void stsDelete(Structs* sts) {
+    for(int i = 0; i < sts->entries; i++) {
+        free(sts->data[i].vars);
+    }
+    free(sts->data);
+}
+
+Struct* stsSearch(Structs* sts, const char* name) {
+    for(int i = 0; i < sts->entries; i++) {
+        if(strcmp(sts->data[i].name, name) == 0) {
+            return sts->data + i;
+        }
+    }
+    return NULL;
+}
+
+Struct* stsAdd(Structs* sts, const char* name) {
+    if(sts->entries >= sts->capacity) {
+        sts->capacity *= 2;
+        sts->data = realloc(sts->data, sizeof(Struct) * sts->capacity);
+    }
+    int index = sts->entries++;
+    sts->data[index].id = index;
+    sts->data[index].amount = 0;
+    sts->data[index].name = name;
+    sts->data[index].vars = NULL;
+    return sts->data + index;
+}

+ 31 - 0
utils/Structs.h

@@ -0,0 +1,31 @@
+#ifndef STRUCTS_H
+#define STRUCTS_H
+
+#include "DataType.h"
+
+typedef struct {
+    const char* name;
+    DataType type;
+} StructVariable;
+
+typedef struct {
+    const char* name;
+    int id;
+    int amount;
+    StructVariable* vars;
+} Struct;
+
+typedef struct {
+    int capacity;
+    int entries;
+    Struct* data;
+} Structs;
+
+void stAddVariable(Struct* st, const char* name, DataType type);
+
+void stsInit(Structs* sts);
+void stsDelete(Structs* sts);
+Struct* stsSearch(Structs* sts, const char* name);
+Struct* stsAdd(Structs* sts, const char* name);
+
+#endif

+ 4 - 1
utils/Variables.c

@@ -10,6 +10,9 @@ void vInit(Variables* v) {
 }
 
 void vDelete(Variables* v) {
+    for(int i = 0; i < v->entries; i++) {
+        free(v->data[i].name);
+    }
     free(v->data);
 }
 
@@ -36,7 +39,7 @@ Variable* vAdd(Variables* v, const char* s, DataType type) {
         v->data = realloc(v->data, sizeof(Variable) * v->capacity);
     }
     int index = v->entries++;
-    v->data[index] = (Variable){s, type, v->address};
+    v->data[index] = (Variable){strdup(s), type, v->address};
     v->address += dtGetSize(type);
     if(v->address > v->maxAddress) {
         v->maxAddress = v->address;

+ 1 - 1
utils/Variables.h

@@ -12,7 +12,7 @@ typedef struct {
 } Scope;
 
 typedef struct {
-    const char* name;
+    char* name;
     DataType type;
     int address;
 } Variable;