Browse Source

basic int references

Kajetan Johannes Hammerle 3 năm trước cách đây
mục cha
commit
ffddc05858
6 tập tin đã thay đổi với 45 bổ sung3 xóa
  1. 21 0
      Compiler.c
  2. 2 1
      tests/struct/reference
  3. 2 2
      tests/struct/reference.out
  4. 2 0
      utils/ByteCodePrinter.c
  5. 2 0
      vm/Operation.h
  6. 16 0
      vm/Script.c

+ 21 - 0
Compiler.c

@@ -209,6 +209,12 @@ static DataType cCallFunction(const char* name) {
 }
 
 static DataType cLoadVariable(Variable* v) {
+    if(dtCompare(v->type, dtToReference(dtInt()))) {
+        cAddOperation(OP_LOAD_INT);
+        cAddInt(v->address);
+        cAddOperation(OP_LOAD_INT_REF);
+        return dtInt();
+    }
     switch(dtAsInt(v->type)) {
         case DT_INT: cAddOperation(OP_LOAD_INT); break;
         case DT_BOOL: cAddOperation(OP_LOAD_BOOL); break;
@@ -223,6 +229,11 @@ static void cStoreVariable(Variable* v, DataType dt, const char* name) {
     if(!dtCompare(v->type, dt)) {
         cInvalidOperation(v->type, dt, name);
     }
+    if(v->type.reference) {
+        cAddOperation(OP_STORE_INT);
+        cAddInt(v->address);
+        return;
+    }
     switch(dtAsInt(v->type)) {
         case DT_INT: cAddOperation(OP_STORE_INT); break;
         case DT_BOOL: cAddOperation(OP_STORE_BOOL); break;
@@ -361,6 +372,16 @@ static DataType cPreUnary() {
             cError("~ needs an int not %s", cGetName(result));
         }
         return result;
+    } else if(cConsumeTokenIf(T_BIT_AND)) {
+        cConsumeToken(T_LITERAL);
+        const char* literal = cReadString();
+        Variable* v = vSearch(&vars, literal);
+        if(v == NULL) {
+            cNotDeclared(literal);
+        }
+        cAddOperation(OP_VAR_REF);
+        cAddInt(v->address);
+        return dtToReference(v->type);
     }
     return cPrimary();
 }

+ 2 - 1
tests/struct/reference

@@ -1,6 +1,7 @@
 void main() {
     int a = 5;
-    int& b = a;
+    int& b = &a;
+    a = 6;
     print a;
     print b;
 }

+ 2 - 2
tests/struct/reference.out

@@ -1,2 +1,2 @@
-5
-5
+6
+6

+ 2 - 0
utils/ByteCodePrinter.c

@@ -119,6 +119,7 @@ static void btConsumeOperation() {
         PRINT_TYPES(INT);
         PRINT_TYPES(BOOL);
         PRINT_TYPES(FLOAT);
+        PRINT_OP(OP_LOAD_INT_REF);
         PRINT_OP(OP_NOTHING);
         PRINT_OP_INT(OP_PUSH_INT);
         PRINT_OP_BASE(OP_PUSH_FLOAT, Float);
@@ -150,6 +151,7 @@ static void btConsumeOperation() {
         PRINT_OP_INT2(OP_GOSUB);
         PRINT_OP_INT(OP_RETURN);
         PRINT_OP_INT2(OP_RESERVE);
+        PRINT_OP_INT(OP_VAR_REF);
         PRINT_OP(OP_INT_ARRAY);
         PRINT_OP_INT(OP_STORE_ARRAY);
         case OP_LINE: sPrintLine(); break;

+ 2 - 0
vm/Operation.h

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

+ 16 - 0
vm/Script.c

@@ -285,6 +285,20 @@ static void sIntArray(Script* sc) {
     (void)sc;
 }
 
+static void sVarRef(Script* sc) {
+    int address = 0;
+    if(sReadInt(sc, &address)) {
+        sPushInt(sc, address + sc->stackVarIndex);
+    }
+}
+
+static void sLoadIntRef(Script* sc) {
+    int address = 0;
+    if(sPopInt(sc, &address) && sCheckAddress(sc, address, sizeof(int))) {
+        sPush(sc, sc->stack + address, sizeof(int));
+    }
+}
+
 #define CASE_NUMBER_OP(name, op)                                               \
     case OP_##name##_INT: NUMBER_OP(int, Int, op); break;                      \
     case OP_##name##_FLOAT:                                                    \
@@ -312,6 +326,7 @@ static void sConsumeInstruction(Script* sc) {
         CASE_TYPE(INT, Int, int);
         CASE_TYPE(BOOL, Bool, bool);
         CASE_TYPE(FLOAT, Float, float);
+        case OP_LOAD_INT_REF: sLoadIntRef(sc); break;
         case OP_NOTHING: break;
         case OP_PUSH_INT: PUSH_CONSTANT(int, Int); break;
         case OP_PUSH_FLOAT: PUSH_CONSTANT(float, Float); break;
@@ -339,6 +354,7 @@ 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_VAR_REF: sVarRef(sc); break;
         case OP_INT_ARRAY: sIntArray(sc); break;
         case OP_STORE_ARRAY: sStore(sc, sizeof(int)); break;
     }