Kajetan Johannes Hammerle vor 3 Jahren
Ursprung
Commit
31f137f75a
5 geänderte Dateien mit 126 neuen und 65 gelöschten Zeilen
  1. 85 56
      Compiler.c
  2. 6 8
      DataType.c
  3. 0 1
      DataType.h
  4. 30 0
      tests/struct/nested
  5. 5 0
      tests/struct/nested.out

+ 85 - 56
Compiler.c

@@ -15,6 +15,11 @@
 #define RETURN_BUFFER 16
 #define BREAK_BUFFER 32
 
+#define DT_OPERATION(op)                                                       \
+    case DT_INT: cAddOperation(OP_##op##_INT); break;                          \
+    case DT_BOOL: cAddOperation(OP_##op##_BOOL); break;                        \
+    case DT_FLOAT: cAddOperation(OP_##op##_FLOAT); break;
+
 static jmp_buf errorJump;
 static char error[ERROR_LENGTH] = {'\0'};
 
@@ -209,31 +214,39 @@ static DataType cCallFunction(const char* name) {
 }
 
 static void cWalkStruct(Variable* v) {
-    int pointers;
-    if(cConsumeTokenIf(T_ARROW)) {
-        pointers = 1;
-        cAddOperation(OP_REFERENCE);
-    } else if(cConsumeTokenIf(T_POINT)) {
-        pointers = 0;
-    } else {
-        return;
-    }
-    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));
+    int offset = 0;
+    while(true) {
+        int pointers;
+        if(cConsumeTokenIf(T_ARROW)) {
+            pointers = 1;
+            cAddOperation(OP_REFERENCE);
+        } else if(cConsumeTokenIf(T_POINT)) {
+            pointers = 0;
+        } else {
+            break;
+        }
+        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));
+        }
+        cConsumeToken(T_LITERAL);
+        const char* name = cReadString();
+        Variable inner;
+        if(vSearchStruct(&inner, &structs, st, name)) {
+            cError("%s has no member %s", v->name, name);
+        }
+        v->type = inner.type;
+        v->name = inner.name;
+        offset += inner.address;
     }
-    cConsumeToken(T_LITERAL);
-    const char* name = cReadString();
-    Variable inner;
-    if(vSearchStruct(&inner, &structs, st, name)) {
-        cError("%s has no member %s", v->name, name);
+    if(offset > 0) {
+        cAddOperation(OP_PUSH_INT);
+        cAddInt(offset);
+        cAddOperation(OP_ADD_INT);
     }
-    v->type = inner.type;
-    cAddOperation(OP_PUSH_INT);
-    cAddInt(inner.address);
-    cAddOperation(OP_ADD_INT);
 }
 
 static void cReference(Variable* v, int dimension) {
@@ -251,10 +264,12 @@ static void cReference(Variable* v, int dimension) {
 }
 
 static void cLoadRef(Variable* v) {
-    switch(dtAsInt(v->type)) {
-        case DT_INT: cAddOperation(OP_LOAD_INT); break;
-        case DT_BOOL: cAddOperation(OP_LOAD_BOOL); break;
-        case DT_FLOAT: cAddOperation(OP_LOAD_FLOAT); break;
+    if(dtIsPointer(v->type)) {
+        cAddOperation(OP_LOAD_INT);
+        return;
+    }
+    switch(v->type.type) {
+        DT_OPERATION(LOAD);
         case DT_STRUCT:
             {
                 Struct* st = dtGetStruct(&structs, v->type);
@@ -265,12 +280,7 @@ static void cLoadRef(Variable* v) {
                 cAddInt(dtGetSize(v->type, &structs));
                 break;
             }
-        default:
-            if(dtIsPointer(v->type)) {
-                cAddOperation(OP_LOAD_INT);
-            } else {
-                cError("cannot load type %s", cGetName(v->type));
-            }
+        default: cError("cannot load type %s", cGetName(v->type));
     }
 }
 
@@ -278,16 +288,13 @@ static void cStore(Variable* v, DataType dt, const char* name) {
     if(!dtCompare(v->type, dt)) {
         cInvalidOperation(v->type, dt, name);
     }
-    switch(dtAsInt(v->type)) {
-        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:
-            if(dtIsPointer(v->type)) {
-                cAddOperation(OP_STORE_ARRAY);
-            } else {
-                cError("cannot store type %s", cGetName(v->type));
-            }
+    if(dtIsPointer(v->type)) {
+        cAddOperation(OP_STORE_ARRAY);
+        return;
+    }
+    switch(v->type.type) {
+        DT_OPERATION(STORE);
+        default: cError("cannot store type %s", cGetName(v->type));
     }
 }
 
@@ -385,10 +392,12 @@ static DataType cPreChange(int change, const char* name) {
 static DataType cPreUnary() {
     if(cConsumeTokenIf(T_SUB)) {
         DataType result = cPrimary();
-        switch(dtAsInt(result)) {
-            case DT_INT: cAddOperation(OP_INVERT_SIGN_INT); break;
-            case DT_FLOAT: cAddOperation(OP_INVERT_SIGN_FLOAT); break;
-            default: cError("cannot invert sign of %s", cGetName(result));
+        if(dtCompare(result, dtInt())) {
+            cAddOperation(OP_INVERT_SIGN_INT);
+        } else if(dtCompare(result, dtFloat())) {
+            cAddOperation(OP_INVERT_SIGN_FLOAT);
+        } else {
+            cError("cannot invert sign of %s", cGetName(result));
         }
         return result;
     } else if(cConsumeTokenIf(T_INCREMENT)) {
@@ -729,21 +738,27 @@ static void cReturn() {
     if(!dtCompare(dt, returnType)) {
         cError("wrong return type, should be %s", cGetName(returnType));
     }
-    switch(dtAsInt(dt)) {
-        case DT_INT: cAddReturn(OP_RETURN_INT); break;
-        case DT_BOOL: cAddReturn(OP_RETURN_BOOL); break;
-        case DT_FLOAT: cAddReturn(OP_RETURN_FLOAT); break;
-        default: cError("cannot return %s", cGetName(dt));
+    if(dtCompare(dt, dtInt())) {
+        cAddReturn(OP_RETURN_INT);
+    } else if(dtCompare(dt, dtBool())) {
+        cAddReturn(OP_RETURN_BOOL);
+    } else if(dtCompare(dt, dtFloat())) {
+        cAddReturn(OP_RETURN_FLOAT);
+    } else {
+        cError("cannot return %s", cGetName(dt));
     }
     cConsumeToken(T_SEMICOLON);
 }
 
 static void cPrint() {
     DataType dt = cExpression();
-    switch(dtAsInt(dt)) {
-        case DT_INT: cAddOperation(OP_PRINT_INT); break;
-        case DT_FLOAT: cAddOperation(OP_PRINT_FLOAT); break;
-        case DT_BOOL: cAddOperation(OP_PRINT_BOOL); break;
+    if(dtIsPointer(dt)) {
+        cAddOperation(OP_PRINT_INT);
+        cConsumeToken(T_SEMICOLON);
+        return;
+    }
+    switch(dt.type) {
+        DT_OPERATION(PRINT);
         default: cError("cannot print type %s", cGetName(dt));
     }
     cConsumeToken(T_SEMICOLON);
@@ -1065,6 +1080,7 @@ static void cStruct() {
         cError("struct registered twice");
     }
     Struct* st = stsAdd(&structs, name);
+    DataType self = dtStruct(st);
     cConsumeToken(T_OPEN_CURVED_BRACKET);
     while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
         Token t = cReadTokenAndLine();
@@ -1073,9 +1089,22 @@ static void cStruct() {
             case T_INT: dt = dtInt(); break;
             case T_BOOL: dt = dtBool(); break;
             case T_FLOAT: dt = dtFloat(); break;
+            case T_LITERAL:
+                {
+                    const char* name = cReadString();
+                    Struct* st = stsSearch(&structs, name);
+                    if(st == NULL) {
+                        cError("struct %s does not exist");
+                    }
+                    dt = dtStruct(st);
+                    break;
+                }
             default: cUnexpectedToken(t);
         }
         dt = cExtendType(dt);
+        if(dtCompare(dt, self)) {
+            cError("struct %s contains itself", name);
+        }
         cConsumeToken(T_LITERAL);
         const char* name = cReadString();
         stAddVariable(st, name, dt);

+ 6 - 8
DataType.c

@@ -38,7 +38,10 @@ const char* dtGetName(Structs* sts, DataType dt) {
 }
 
 int dtGetSize(DataType dt, Structs* sts) {
-    switch(dtAsInt(dt)) {
+    if(dt.pointers > 0) {
+        return sizeof(int);
+    }
+    switch(dt.type) {
         case DT_INT: return sizeof(int);
         case DT_FLOAT: return sizeof(float);
         case DT_BOOL: return sizeof(bool);
@@ -96,19 +99,14 @@ DataType dtToArray(DataType dt, int dimension) {
 }
 
 bool dtCompare(DataType a, DataType b) {
-    return dtAsInt(a) == dtAsInt(b);
+    return a.pointers == b.pointers && a.structId == b.structId &&
+           a.type == b.type;
 }
 
 int dtMaxDimensions() {
     return 15;
 }
 
-unsigned int dtAsInt(DataType dt) {
-    unsigned int i;
-    memcpy(&i, &dt, sizeof(dt));
-    return i;
-}
-
 bool dtIsPointer(DataType dt) {
     return dt.pointers > 0;
 }

+ 0 - 1
DataType.h

@@ -50,7 +50,6 @@ Struct* dtGetStruct(Structs* sts, DataType dt);
 bool dtCompare(DataType a, DataType b);
 int dtMaxDimensions();
 const char* dtGetName(Structs* sts, DataType dt);
-unsigned int dtAsInt(DataType dt);
 
 void stAddVariable(Struct* st, const char* name, DataType type);
 

+ 30 - 0
tests/struct/nested

@@ -0,0 +1,30 @@
+struct A {
+    int a;
+    int b;
+};
+
+struct B {
+    int a;
+    int b;
+    int c;
+    A d;
+};
+
+
+void main() {
+    B b;
+    b.a = 1;
+    b.b = 2;
+    b.c = 3;
+    b.d.a = 3;
+    b.d.b = 5;
+    
+    B* ba = &b;
+    ba->d.a = 4;
+    
+    print b.a;
+    print b.b;
+    print b.c;
+    print b.d.a;
+    print b.d.b;
+}

+ 5 - 0
tests/struct/nested.out

@@ -0,0 +1,5 @@
+1
+2
+3
+4
+5