]> git.mdlowis.com Git - proto/obnc.git/commitdiff
implemented record types and record member access
authormike lowis <mike@mdlowis.com>
Wed, 26 May 2021 00:43:09 +0000 (20:43 -0400)
committermike lowis <mike@mdlowis.com>
Wed, 26 May 2021 00:43:09 +0000 (20:43 -0400)
cerise/backend/c99/codegen.c
cerise/backend/test/codegen.c
cerise/backend/x86_64/codegen.c
cerise/inc/cerise.h
cerise/src/grammar.c
cerise/tests/Module.m

index 1db17e90b75e5c3d8df640a0b1df245380a1d2b4..4d22b4aae426ec5c38af6b17bf36edac06a6cc20 100644 (file)
@@ -23,9 +23,9 @@ Type StringType = {
 };
 
 static char* TypeNames[FORM_COUNT] = {
-    [FORM_BOOL]   = "_Bool",
-    [FORM_INT]    = "long",
-    [FORM_REAL]   = "double",
+    [FORM_BOOL]   = "Bool",
+    [FORM_INT]    = "Int",
+    [FORM_REAL]   = "Real",
     [FORM_STRING] = "char*"
 };
 
@@ -47,7 +47,35 @@ static char* Operators[] = {
 //    [IS]   = ???
 };
 
-static void declare_var(Parser* p, Symbol* sym, int isref)
+char* typetoptr(Type* type)
+{
+    if (type->form == FORM_BOOL)
+    {
+        return "Bool*";
+    }
+    else if (type->form == FORM_INT)
+    {
+        return "Int*";
+    }
+    else if (type->form == FORM_REAL)
+    {
+        return "Real*";
+    }
+//    else if (type->form == FORM_ARRAY)
+//    {
+//        return "(*)[]";
+//    }
+//    else if (type->form == FORM_RECORD)
+//    {
+//        return
+//    }
+    else
+    {
+        assert(!"unimplemented type output");
+    }
+}
+
+static void make_var(Parser* p, Symbol* sym, int isref)
 {
     char name[8192];
     if (sym->global)
@@ -57,7 +85,6 @@ static void declare_var(Parser* p, Symbol* sym, int isref)
      }
     else
     {
-        printf("    ");
         snprintf(name, sizeof(name), "(%c%s)",
             (char)(isref ? '*' : ' '), sym->name);
     }
@@ -72,12 +99,26 @@ static void declare_var(Parser* p, Symbol* sym, int isref)
             printf("[%d]", type->size);
         }
     }
+    else if (sym->type->form == FORM_RECORD)
+    {
+        printf("char %s[%d]", name, sym->type->size);
+    }
     else
     {
         printf("%s %s", TypeNames[sym->type->form], name);
     }
 }
 
+static void declare_var(Parser* p, Symbol* sym, int isref)
+{
+    if (!sym->global)
+    {
+        printf("    ");
+    }
+    make_var(p, sym, isref);
+}
+
+
 static int declare_temp(Parser* p, Type* type, int isref)
 {
     char name[32];
@@ -88,16 +129,44 @@ static int declare_temp(Parser* p, Type* type, int isref)
         .name = name,
         .type = type,
     };
-    declare_var(p, &sym, isref);
+    if (type->form == FORM_RECORD)
+    {
+        printf("    char* %s", name);
+    }
+    else
+    {
+        declare_var(p, &sym, isref);
+    }
     p->curr_reg++;
     return reg;
 }
 
+static char* temp(Item* a)
+{
+    char name[32];
+    if (a->mode == ITEM_INDEX)
+    {
+        snprintf(name, sizeof(name), "(*_T%d)", a->reg);
+    }
+    else if (a->mode == ITEM_FIELD)
+    {
+        snprintf(name, sizeof(name), "*((%s)_T%d)", typetoptr(a->type), a->reg);
+    }
+    else
+    {
+        snprintf(name, sizeof(name), "(_T%d)", a->reg);
+    }
+    return strdup(name);
+}
+
 static void load_var(Parser* p, Item* item)
 {
     if (!item->reg)
     {
-        int isref = (item->type->form == FORM_ARRAY);
+        int isref = (
+               (item->type->form == FORM_ARRAY)
+            || (item->type->form == FORM_RECORD)
+        );
         switch (item->mode)
         {
             case ITEM_CONST:
@@ -108,13 +177,26 @@ static void load_var(Parser* p, Item* item)
 
             case ITEM_VAR:
                 item->reg = declare_temp(p, item->type, isref);
-                printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
+                if (item->type->form == FORM_RECORD)
+                {
+                    printf(" = (char*)&%s[0];\n", item->imm.s);
+                }
+                else
+                {
+                    printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
+                }
                 break;
 
             case ITEM_MVAR:
                 item->reg = declare_temp(p, item->type, isref);
-                printf(" = %c%s_%s;\n",
-                    (isref ? '&' : ' '), p->name, item->imm.s);
+                if (item->type->form == FORM_RECORD)
+                {
+                    printf(" = &%s_%s[0];\n", p->name, item->imm.s);
+                }
+                else
+                {
+                    printf(" = %c%s_%s;\n", (isref ? '&' : ' '), p->name, item->imm.s);
+                }
                 break;
 
             default:
@@ -123,15 +205,6 @@ static void load_var(Parser* p, Item* item)
     }
 }
 
-static char* temp(Item* a)
-{
-    char name[32];
-    snprintf(name, sizeof(name), "(%c_T%d)",
-        (a->mode == ITEM_INDEX ? '*' : ' '),
-        a->reg);
-    return strdup(name);
-}
-
 /* Operator Handling
  *****************************************************************************/
 static void binary_op(Parser* p, int op, Item* a, Item* b)
@@ -214,7 +287,7 @@ void codegen_startproc(Parser* p, Symbol* proc)
             proc->name);
         for (Symbol* arg = proc->desc; arg; arg = arg->next)
         {
-            printf("%s %s", TypeNames[arg->type->form], arg->name);
+            make_var(p, arg, false);
             if (arg->next)
             {
                 printf(", ");
@@ -280,6 +353,12 @@ void codegen_store(Parser* p, Item* a, Item* b)
         load_var(p, b);
         printf("    %s = %s;\n", temp(a), temp(b));
     }
+    else if (a->mode == ITEM_FIELD)
+    {
+        load_var(p, b);
+//        printf("    *((%s)%s) = %s;\n", typetoptr(a->type), temp(a), temp(b));
+        printf("    %s = %s;\n", temp(a), temp(b));
+    }
     else
     {
         assert(!"bad store op");
@@ -377,3 +456,33 @@ void codegen_index(Parser* p, Item* array, Item* index)
     printf(" = &%s[%s];\n", temp(array), temp(index));
     array->reg = dest_reg;
 }
+
+Field* get_field(Parser* p, Type* type, char* name)
+{
+    Field* curr = type->fields;
+    while (curr)
+    {
+        if (curr->name && !strcmp(curr->name, name))
+        {
+            break;
+        }
+        curr = curr->next;
+    }
+    if (!curr)
+    {
+        error(p, "record has no such field '%s'\n", name);
+    }
+    return curr;
+}
+
+void codegen_field(Parser* p, Item* record, char* name)
+{
+    load_var(p, record);
+    Field* f = get_field(p, record->type, name);
+    record->mode = ITEM_FIELD;
+    record->type = f->type;
+    printf("    char* _T%d", p->curr_reg);
+    p->curr_reg++;
+    printf(" = _T%d + %ld;\n", record->reg, f->offset);
+    record->reg = p->curr_reg-1;
+}
index 3502455d54cc8043b1dc78324723db19b596f401..91ebd3298b5c3439b321a5672b75580453333728 100644 (file)
@@ -125,3 +125,9 @@ void codegen_index(Parser* p, Item* array, Item* index)
 {
     (void)p, (void)array, (void)index;
 }
+
+void codegen_field(Parser* p, Item* record, char* name)
+{
+    (void)p, (void)record, (void)name;
+}
+
index db4efabdb2d0cbcfa53f696fd56635601da4c0dd..85023cb2110257e742af6f57dd81f77ade2da6a1 100644 (file)
@@ -355,3 +355,8 @@ void codegen_index(Parser* p, Item* array, Item* index)
 {
     (void)p, (void)array, (void)index;
 }
+
+void codegen_field(Parser* p, Item* record, char* name)
+{
+    (void)p, (void)record, (void)name;
+}
index 25d4f671ebe81ac6f54feb9cd10a1eaccc748848..59c1ec67f8e4ca500bcec6266b2b6e67cd50bf9c 100644 (file)
@@ -128,7 +128,7 @@ typedef struct Module {
 typedef struct Item {
     struct Item* next;
     enum {
-        ITEM_CONST, ITEM_VAR, ITEM_MVAR, ITEM_REG, ITEM_INDEX
+        ITEM_CONST, ITEM_VAR, ITEM_MVAR, ITEM_REG, ITEM_INDEX, ITEM_FIELD
     } mode;
     Symbol* sym;
     Type* type;
@@ -222,6 +222,7 @@ void codegen_call(Parser* p, Item* item, Item* args);
 void codegen_setarg(Parser* p, Item* item, bool firstarg);
 void codegen_return(Parser* p, Item* item);
 void codegen_index(Parser* p, Item* array, Item* index);
+void codegen_field(Parser* p, Item* record, char* name);
 
 /*
 
index ec56a0f5c1f90b8604db929e825b0141bd14ba14..595a8092f4a4d1ccf5f49c28f2b89c02596ddc86 100644 (file)
@@ -169,9 +169,20 @@ RULE(designator)
     {
         switch ((int)peek(p)->type)
         {
-    //        case '.':
-    //            expect(p, IDENT);
-    //            break;
+            case '.':
+            {
+                expect(p, '.');
+                char* name = expect_text(p, IDENT);
+                if (item->type->form == FORM_RECORD)
+                {
+                    codegen_field(p, item, name);
+                }
+                else
+                {
+                    error(p, "attempting to access field of non-array object");
+                }
+                break;
+            }
 
             case '[':
             {
index 52f0504be546e9e2484013ff664f9190dbe8e50b..64f8e5c87c6965fabc19b953ff29ed7c3db8a363 100644 (file)
@@ -15,6 +15,9 @@ type
   TypeD = record
     x,y : Int
     label : array 10 of Real
+    dim : record
+      w,h : Int
+    end
   end
 
 var
@@ -23,8 +26,9 @@ var
   c : Int
   d : Real
   e : array 5 of array 10 of Int
+  f : TypeD
 
-procedure Foo*(e : Int, z : Int) : Int
+procedure Foo*(e : Int, z : Int, q1 : TypeD, q2 : array 5 of Int) : Int
   const FOO = 2
   type foo = Int
   var
@@ -108,4 +112,6 @@ begin
 #  e[b] = 1;
 #    e[1][2] = 1;
 #    c = e[1][c];
+  c = f.dim.w;
+  f.dim.h = 0;
 end