]> git.mdlowis.com Git - proto/obnc.git/commitdiff
scaffolding is in place for assignment statements. Need to decipher level handling...
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Apr 2021 13:46:52 +0000 (09:46 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 22 Apr 2021 13:46:52 +0000 (09:46 -0400)
cerise/build.sh
cerise/cerise.h
cerise/codegen.c
cerise/oberon0/OSG.Mod
cerise/parser.c

index 6328d79d4f93d36d5de8a3f672b0ba3dd53888bd..a6d65d1afd971ab64a645827a478ac637934daca 100755 (executable)
@@ -2,6 +2,6 @@
 ctags -R &
 cc -g -D CERISE_TESTS -Wall -Wextra --std=c99 -o cerisec-test *.c \
   && ./cerisec-test \
-  && cc -g -Wall -Wextra -Werror --std=c99 -o cerisec *.c \
+  && cc -g -Wall -Wextra --std=c99 -o cerisec *.c \
   && ./cerisec tests/Module.m
 #[ $? -gt 0 ] && printf "\a"
index 84339aa8e61c2953d750216e2dcb5d1b90724baa..5b6a02d4f6b82550dda61eed9048f0ab366939d8 100644 (file)
@@ -134,7 +134,9 @@ extern Type BoolType, IntType, RealType, StringType;
 void codegen_setint(Item* item, Type* type, long long val);
 void codegen_setreal(Item* item, double val);
 void codegen_setstr(Item* item, char* val);
+
 void codegen_unop(int op, Item* a);
 void codegen_binop(int op, Item* a, Item* b);
 void codegen_startproc(char* name, long long localsz);
 void codegen_endproc(void);
+void codegen_store(Item* a, Item* b);
index 860191386b2c8b4a2da6231bde058884214d26cd..5e2708f24088fcbdec6a70e46f81fa79176f11bd 100644 (file)
@@ -225,3 +225,8 @@ void codegen_endproc(void)
     printf("    pop      %%rbp\n");
     printf("    ret\n");
 }
+
+void codegen_store(Item* a, Item* b)
+{
+    (void)a, (void)b;
+}
index f54a5c113eb8260ee6f11ed29104c81112d40ed4..29e87532aa6463816beba01c4dceecd0d880fb0f 100644 (file)
@@ -188,9 +188,18 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX  9.5.2017*)
 \r
   PROCEDURE MakeItem*(VAR x: Item; y: Object; curlev: LONGINT);\r
     VAR r: LONGINT;\r
-  BEGIN x.mode := y.class; x.type := y.type; x.a := y.val; x.r := y.lev;\r
-    IF y.class = Par THEN x.b := 0 END ;\r
-    IF (y.lev > 0) & (y.lev # curlev) & (y.class # Const) THEN OSS.Mark("level error") END\r
+  BEGIN\r
+    x.mode := y.class;\r
+    x.type := y.type;\r
+    x.a := y.val;\r
+    x.r := y.lev;\r
+\r
+    IF y.class = Par THEN\r
+        x.b := 0\r
+    END ;\r
+    IF (y.lev > 0) & (y.lev # curlev) & (y.class # Const) THEN\r
+        OSS.Mark("level error")\r
+    END\r
   END MakeItem;\r
 \r
   PROCEDURE Field*(VAR x: Item; y: Object);   (* x := x.y *)\r
index c91309e1ce65550915b581d7b705b69327322577..5a5e20c690bd4b064a7f1d763c9ff4b5538bd206 100644 (file)
@@ -136,13 +136,23 @@ static Symbol* symbol_new(Parser* p, char* name, int class, bool export)
     return sym;
 }
 
-static Symbol* symbol_get(Parser* p, char* name)
+static Symbol* symbol_get(Parser* p, int class, char* name)
 {
     Symbol* sym = p->scope;
     for (; sym; sym = sym->next)
     {
         if (!strcmp(sym->name, name))
         {
+            if (class >= 0 && (int)sym->class != class)
+            {
+                switch(class)
+                {
+                    case SYM_CONST: error(p, "'%s' is not a constant", name); break;
+                    case SYM_VAR:   error(p, "'%s' is not a variable", name); break;
+                    case SYM_TYPE:  error(p, "'%s' is not a type", name);     break;
+                    default:        assert(!"unknown identifier type");       break;
+                }
+            }
             return sym;
         }
     }
@@ -150,6 +160,15 @@ static Symbol* symbol_get(Parser* p, char* name)
     return NULL;
 }
 
+/* Item Handling
+ *****************************************************************************/
+static void init_item(Item* item, Symbol* sym)
+{
+    item->mode = sym->class;
+    item->imm  = sym->imm;
+    item->type = sym->type;
+}
+
 /* Type Checking
  *****************************************************************************/
 static void check_int(Parser* p, Item* item)
@@ -160,7 +179,7 @@ static void check_int(Parser* p, Item* item)
     }
 }
 
-static void check_int2(Parser* p, Item* a, Item* b)
+static void check_ints(Parser* p, Item* a, Item* b)
 {
     check_int(p, a);
     check_int(p, b);
@@ -174,7 +193,7 @@ static void check_real(Parser* p, Item* item)
     }
 }
 
-static void check_real2(Parser* p, Item* a, Item* b)
+static void check_reals(Parser* p, Item* a, Item* b)
 {
     check_real(p, a);
     check_real(p, b);
@@ -192,15 +211,15 @@ static void check_num(Parser* p, Item* a)
     }
 }
 
-static void check_num2(Parser* p, Item* a, Item* b)
+static void check_nums(Parser* p, Item* a, Item* b)
 {
     if (a->type->form == FORM_REAL)
     {
-        check_real2(p, a, b);
+        check_reals(p, a, b);
     }
     else
     {
-        check_int2(p, a, b);
+        check_ints(p, a, b);
     }
 }
 
@@ -212,12 +231,28 @@ static void check_bool(Parser* p, Item* item)
     }
 }
 
-static void check_bool2(Parser* p, Item* a, Item* b)
+static void check_bools(Parser* p, Item* a, Item* b)
 {
     check_bool(p, a);
     check_bool(p, b);
 }
 
+static void check_types(Parser* p, Item* a, Item* b)
+{
+    if (a->type->form == FORM_REAL)
+    {
+        check_reals(p, a, b);
+    }
+    else if (a->type->form == FORM_INT)
+    {
+        check_ints(p, a, b);
+    }
+    else
+    {
+        error(p, "type mismatch");
+    }
+}
+
 /* Grammar Definition
  *****************************************************************************/
 
@@ -238,13 +273,19 @@ static void expression(Parser* p, Item* item);
 RULE(qualident)
 {
     char* name = expect_text(p, IDENT);
-    Symbol* sym = symbol_get(p, name);
+    Symbol* sym = symbol_get(p, -1, name);
+    init_item(item, sym);
+
+//    item->mode = sym->class;
+//    item->type = sym->type;
+//    item->imm  = sym->imm;
+
+//    if (sym->class == SYM_CONST)
+//    {
+//        item->mode = ITEM_CONST;
+//        item->imm = sym->imm;
+//    }
 
-    if (sym->class == SYM_CONST)
-    {
-        item->mode = ITEM_CONST;
-        item->imm = sym->imm;
-    }
 //    if (accept(p, '.'))
 //    {
 //        expect(p, IDENT);
@@ -340,12 +381,12 @@ RULE(term)
             case '*':
             case '/':
             case '%':
-                check_num2(p, item, &right);
+                check_nums(p, item, &right);
                 codegen_binop(op, item, &right);
                 break;
 
             case AND:
-                check_bool2(p, item, &right);
+                check_bools(p, item, &right);
                 codegen_binop(op, item, &right);
                 break;
 
@@ -379,11 +420,11 @@ RULE(simple_expr)
         term(p, &right);
         if (op == OR)
         {
-            check_bool2(p, item, &right);
+            check_bools(p, item, &right);
         }
         else
         {
-            check_num2(p, item, &right);
+            check_nums(p, item, &right);
         }
         codegen_binop(op, item, &right);
     }
@@ -398,7 +439,7 @@ RULE(expression)
         Item right = { 0 };
         int op = consume(p);
         simple_expr(p, &right);
-        check_num2(p, item, &right);
+        check_nums(p, item, &right);
         codegen_binop(op, item, &right);
     }
 }
@@ -427,15 +468,7 @@ RULE(var_decl)
 
     expect(p, ':');
     name = expect_text(p, IDENT);
-    type = symbol_get(p, name);
-    if (!type)
-    {
-        error(p, "unknown type identifier '%'\n", name);
-    }
-    if (type->class != SYM_TYPE)
-    {
-        error(p, "'%' is not a type identifier\n", name);
-    }
+    type = symbol_get(p, SYM_TYPE, name);
 
     /* apply the type to the newly created symbols */
     for (int i = 0; i < nsyms; i++)
@@ -464,6 +497,7 @@ RULE(const_decl)
         expect(p, '=');
         expression(p, item);
         sym->imm = item->imm;
+        sym->type = item->type;
 
         if (!accept(p, ','))
         {
@@ -472,26 +506,73 @@ RULE(const_decl)
     }
 }
 
+/* Code generation for
+find(obj);
+OSS.Get(sym);
+IF obj.class = OSG.SProc THEN
+  StandProc(obj.val)
+ELSE
+  OSG.MakeItem(x, obj, level);
+  selector(x);
+
+  IF sym = OSS.becomes THEN (*assignment*)
+
+    OSS.Get(sym);
+    expression(y);
+    IF (x.type.form IN {OSG.Boolean, OSG.Integer}) & (x.type.form = y.type.form) THEN
+      OSG.Store(x, y)
+    ELSE
+      OSS.Mark("incompatible assignment")
+    END
+
+//  ELSIF sym = OSS.eql THEN
+//    OSS.Mark("should be :=");
+//    OSS.Get(sym);
+//    expression(y)
+//  ELSIF sym = OSS.lparen THEN (*procedure call*)
+//    OSS.Get(sym);
+//    IF (obj.class = OSG.Proc) & (obj.type = NIL) THEN
+//      ParamList(obj);
+//      OSG.Call(obj);
+//    ELSE
+//      OSS.Mark("not a procedure")
+//    END
+//  ELSIF obj.class = OSG.Proc THEN (*procedure call without parameters*)
+//    IF obj.nofpar > 0 THEN
+//      OSS.Mark("missing parameters")
+//    END ;
+//    IF obj.type = NIL THEN
+//      OSG.Call(obj) ELSE
+//      OSS.Mark("not a procedure")
+//    END
+//  ELSIF (obj.class = OSG.SProc) & (obj.val = 3) THEN
+//    OSG.WriteLn
+//  ELSIF obj.class = OSG.Typ THEN
+//    OSS.Mark("illegal assignment")
+//  ELSE
+//    OSS.Mark("not a procedure")
+//  END
+END
+
+*/
+
 RULE(statement_seq)
 {
     if (matches(p, IDENT))
     {
+        Item right = { 0 };
         char* text = expect_text(p, IDENT);
         if (accept(p, '='))
         {
-            Symbol* sym = symbol_get(p, text);
-            if (!sym)
-            {
-                error(p, "undefined variable '%s'", text);
-            }
-            else if (sym->class != SYM_VAR)
-            {
-                error(p, "assignment to non-variable '%s'", text);
-            }
-            expression(p, item);
+            Symbol* sym = symbol_get(p, SYM_VAR, text);
+            init_item(item, sym);
+            expression(p, &right);
+            check_types(p, item, &right);
+            codegen_store(item, &right);
         }
         else
         {
+            /* TODO: add function calls and other complex stuff */
             error(p, "expected assignment");
         }
     }
@@ -578,12 +659,12 @@ RULE(module)
     expect(p, ';');
 }
 
-static inline char* file_load(char* path) 
+static inline char* file_load(char* path)
 {
     int fd = -1, nread = 0, length = 0;
     struct stat sb = {0};
     char* contents = NULL;
-    if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) 
+    if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0))
     {
         contents = calloc(sb.st_size + 1u, 1u);
         while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0)
@@ -591,7 +672,7 @@ static inline char* file_load(char* path)
             length += nread, sb.st_size -= nread;
         }
     }
-    if (fd > 0) 
+    if (fd > 0)
     {
         close(fd);
     }
@@ -609,7 +690,7 @@ void compile(char* fname)
                 .fbeg  = fcontents,
                 .fpos  = fcontents,
             }
-        }, 
+        },
         &(Item){0}
     );