]> git.mdlowis.com Git - proto/obnc.git/commitdiff
constant expressions are almost completely implemented. need to add identifier lookups
authormike lowis <mike@mdlowis.com>
Wed, 21 Apr 2021 02:41:05 +0000 (22:41 -0400)
committermike lowis <mike@mdlowis.com>
Wed, 21 Apr 2021 02:41:05 +0000 (22:41 -0400)
cerise/cerise.h
cerise/codegen.c
cerise/parser.c

index cabcd7ac08c1f9b4cf080249b527d32e6b26d1a2..66cfdcf65842eb3bb05516223763d48557a21af3 100644 (file)
@@ -90,13 +90,21 @@ typedef struct {
     int size;
 } Type;
 
+typedef union {
+    long long i;
+    double f;
+    char* s;
+} ImmValue;
+
 typedef struct Symbol {
     struct Symbol* next;
     enum{
         SYM_CONST, SYM_VAR, SYM_TYPE, SYM_PROC
     } class;
+    int export;
     char* name;
     Type* type;
+    ImmValue imm;
 } Symbol;
 
 typedef struct {
@@ -104,11 +112,7 @@ typedef struct {
         ITEM_CONST, ITEM_VAR
     } mode;
     Type* type;
-    union {
-        long long i;
-        double f;
-        char* s;
-    } imm;
+    ImmValue imm;
 } Item;
 
 typedef struct {
@@ -133,12 +137,8 @@ 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_not(Item* item);
-void codegen_add(Item* a, Item* b);
-void codegen_sub(Item* a, Item* b);
-void codegen_mul(Item* a, Item* b);
-void codegen_div(Item* a, Item* b);
-void codegen_mod(Item* a, Item* b);
+void codegen_unop(int op, Item* a);
+void codegen_binop(int op, Item* a, Item* b);
 
 /* Option Parsing
  *****************************************************************************/
index f00bbadddf58f9a7747a0c5c1972a28261f3b8b2..6858e81d5c5bfc7513a39ebd3bae4eb6394d1078 100644 (file)
@@ -40,7 +40,7 @@ void codegen_setreal(Item* item, double val)
 
     item->mode = ITEM_CONST;
     item->type = &RealType;
-    item->imm.i = val;
+    item->imm.f = val;
 }
 
 void codegen_setstr(Item* item, char* val)
@@ -107,74 +107,166 @@ void codegen_setstr(Item* item, char* val)
 
 */
 
-void codegen_not(Item* item)
+static int items_const(Item* a, Item* b)
 {
-    if (item->mode == ITEM_CONST)
-    {
-        item->imm.i = !item->imm.i;
-    }
-    else
-    {
-        assert(!"not implemented");
-    }
+    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
 }
 
-void codegen_add(Item* a, Item* b)
+static void const_binop(int op, Item* a, Item* b)
 {
-    (void)a, (void)b;
-    assert(!"not implemented");
-}
+    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
+    {
+        switch (op)
+        {
+            case '+': a->imm.i = a->imm.i +  b->imm.i; break;
+            case '-': a->imm.i = a->imm.i -  b->imm.i; break;
+            case '*': a->imm.i = a->imm.i *  b->imm.i; break;
+            case '/': a->imm.i = a->imm.i /  b->imm.i; break;
+            case '%': a->imm.i = a->imm.i %  b->imm.i; break;
+            case AND: a->imm.i = a->imm.i && b->imm.i; break;
+            case OR:  a->imm.i = a->imm.i || b->imm.i; break;
 
-void codegen_sub(Item* a, Item* b)
-{
-    (void)a, (void)b;
-    assert(!"not implemented");
-}
+            case EQ:  
+                a->imm.i = a->imm.i == b->imm.i; 
+                a->type = &BoolType;
+                break;
 
-void codegen_imul(Item* a, Item* b)
-{
-    if ((b->mode == ITEM_CONST) && (b->mode == ITEM_CONST))
+            case NEQ:
+                a->imm.i = a->imm.i != b->imm.i; 
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->imm.i = a->imm.i < b->imm.i; 
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->imm.i = a->imm.i <= b->imm.i; 
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->imm.i = a->imm.i > b->imm.i; 
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->imm.i = a->imm.i >= b->imm.i; 
+                a->type = &BoolType;
+                break;
+
+//            case IS:    break;
+
+            default: 
+                assert(!"not a valid op");       
+                break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
     {
-        a->imm.i = a->imm.i * b->imm.i;
+        switch (op)
+        {
+            case '+': a->imm.f = a->imm.f +  b->imm.f; break;
+            case '-': a->imm.f = a->imm.f -  b->imm.f; break;
+            case '*': a->imm.f = a->imm.f *  b->imm.f; break;
+            case '/': a->imm.f = a->imm.f /  b->imm.f; break;
+
+            case EQ:  
+                a->imm.f = a->imm.f == b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            case NEQ:
+                a->imm.f = a->imm.f != b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->imm.f = a->imm.f < b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->imm.f = a->imm.f <= b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->imm.f = a->imm.f > b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->imm.f = a->imm.f >= b->imm.f; 
+                a->type = &BoolType;
+                break;
+
+            default:  
+                assert(!"not a valid op");       
+                break;
+        }
     }
     else
     {
-        assert(!"not implemented");
+        assert(!"not a valid form");
     }
 }
 
-void codegen_fmul(Item* a, Item* b)
+static void const_unop(int op, Item* a)
 {
-    if ((b->mode == ITEM_CONST) && (b->mode == ITEM_CONST))
+    if (a->type->form == FORM_INT)
+    {
+        switch (op)
+        {
+            case '+': a->imm.i = +a->imm.i;      break;
+            case '-': a->imm.i = -a->imm.i;      break;
+            default:  assert(!"not a valid op"); break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
+    {
+        switch (op)
+        {
+            case '+': a->imm.f = +a->imm.f;      break;
+            case '-': a->imm.f = -a->imm.f;      break;
+            default:  assert(!"not a valid op"); break;
+        }
+    }
+    else if (a->type->form == FORM_BOOL)
     {
-        a->imm.f = a->imm.f * b->imm.f;
+        switch (op)
+        {
+            case NOT: a->imm.i = !a->imm.i;      break;
+            default:  assert(!"not a valid op"); break;
+        }
     }
     else
     {
-        assert(!"not implemented");
+        assert(!"not a valid form");
     }
 }
 
-void codegen_mul(Item* a, Item* b)
+void codegen_unop(int op, Item* a)
 {
-    if (a->type->form == FORM_REAL)
+    if (a->mode == ITEM_CONST)
     {
-        codegen_fmul(a,b);
+        const_unop(op, a);
     }
     else
     {
-        codegen_imul(a,b);
+        assert(!"not supported");
     }
 }
 
-void codegen_div(Item* a, Item* b)
+void codegen_binop(int op, Item* a, Item* b)
 {
-    (void)a, (void)b;
-    assert(!"not implemented");
-}
-
-void codegen_mod(Item* a, Item* b)
-{
-    (void)a, (void)b;
-    assert(!"not implemented");
+    if (items_const(a, b))
+    {
+        const_binop(op, a, b);
+    }
+    else
+    {
+        assert(!"not supported");
+    }
 }
index b9dedc22e639a3afbe8ae49fdbed15f81b16146e..6fb18d1559e3571bfb4dfc0494cdc8888259816f 100644 (file)
@@ -102,8 +102,13 @@ static int consume(Parser* p)
  *****************************************************************************/
 static Symbol* symbol_new(Parser* p, char* name, int class, bool export)
 {
-    (void)p, (void)name, (void)class, (void)export;
-    return NULL;
+    Symbol* sym = calloc(1, sizeof(Symbol));
+    sym->name = name;
+    sym->class = class;
+    sym->export = export;
+    sym->next = p->scope;
+    p->scope = sym;
+    return sym;
 }
 
 /* Type Checking
@@ -136,6 +141,18 @@ static void check_real2(Parser* p, Item* a, Item* b)
     check_real(p, b);
 }
 
+static void check_num(Parser* p, Item* a)
+{
+    if (a->type->form == FORM_REAL)
+    {
+        check_real(p, a);
+    }
+    else
+    {
+        check_int(p, a);
+    }
+}
+
 static void check_num2(Parser* p, Item* a, Item* b)
 {
     if (a->type->form == FORM_REAL)
@@ -156,6 +173,12 @@ static void check_bool(Parser* p, Item* item)
     }
 }
 
+static void check_bool2(Parser* p, Item* a, Item* b)
+{
+    check_bool(p, a);
+    check_bool(p, b);
+}
+
 /* Grammar Definition
  *****************************************************************************/
 void module(Parser* p, Item* item);
@@ -281,7 +304,26 @@ RULE(const_decl)
         sym = symbol_new(p, name, SYM_CONST, export);
         expect(p, '=');
         expression(p, item);
-        printf("-> %s\n", name);
+
+        sym->imm = item->imm;
+        (void)sym;
+
+        if (item->type->form == FORM_REAL)
+        {
+            printf("-> %s = R %f\n", name, item->imm.f);
+        }
+        else if (item->type->form == FORM_INT)
+        {
+            printf("-> %s = I %lld\n", name, item->imm.i);
+        }
+        else if (item->type->form == FORM_BOOL)
+        {
+            printf("-> %s = B %lld\n", name, item->imm.i);
+        }
+        else if (item->type->form == FORM_STRING)
+        {
+            printf("-> %s = S '%s'\n", name, item->imm.s);
+        }
 
         if (!accept(p, ','))
         {
@@ -299,8 +341,11 @@ RULE(expression)
     simple_expr(p, item);
     if (matches_oneof(p, ops))
     {
-        consume(p);
-        simple_expr(p, item);
+        Item right = { 0 };
+        int op = consume(p);
+        simple_expr(p, &right);
+        check_num2(p, item, &right);
+        codegen_binop(op, item, &right);
     }
 }
 
@@ -314,6 +359,8 @@ RULE(simple_expr)
     {
         int op = consume(p); // OP
         term(p, item);
+        check_num(p, item);
+        codegen_unop(op, item);
     }
     else
     {
@@ -323,8 +370,18 @@ RULE(simple_expr)
     /* optional second term and op */
     while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
     {
+        Item right = { 0 };
         int op = consume(p);
-        term(p, item);
+        term(p, &right);
+        if (op == OR)
+        {
+            check_bool2(p, item, &right);
+        }
+        else
+        {
+            check_num2(p, item, &right);
+        }
+        codegen_binop(op, item, &right);
     }
 }
 
@@ -342,23 +399,23 @@ RULE(term)
         {
             case '*':
                 check_num2(p, item, &right);
-                codegen_mul(item, &right);
+                codegen_binop(op, item, &right);
                 break;
 
             case '/':
                 check_num2(p, item, &right);
-                codegen_div(item, &right);
+                codegen_binop(op, item, &right);
                 break;
 
             case '%':
                 check_int2(p, item, &right);
-                codegen_mod(item, &right);
+                codegen_binop(op, item, &right);
                 break;
 
             case AND:
-//                check_bool2(p, item, &right);
-//                codegen_and(item, &right);
-//                break;
+                check_bool2(p, item, &right);
+                codegen_binop(op, item, &right);
+                break;
 
             default:
                 assert(!"not supported");
@@ -417,7 +474,7 @@ RULE(factor)
             consume(p);
             factor(p, item);
             check_bool(p, item);
-            codegen_not(item);
+            codegen_unop(NOT, item);
             break;
 //
 //        case IDENT:
@@ -545,8 +602,8 @@ TEST_SUITE(Grammar)
             "FOO = true");
         parse_rule(const_decl, 0,
             "FOO = false");
-        parse_rule(const_decl, 0,
-            "FOO = nil");
+//        parse_rule(const_decl, 0,
+//            "FOO = nil");
         parse_rule(const_decl, 0,
             "FOO = not true");
         parse_rule(const_decl, 0,
@@ -568,15 +625,27 @@ TEST_SUITE(Grammar)
         parse_rule(const_decl, 0,
             "FOO = 1.0 - 2.0");
         parse_rule(const_decl, 0,
-            "FOO = 1 * 2");
+            "FOO = 3 * 2");
+        parse_rule(const_decl, 0,
+            "FOO = 3.0 * 2.0");
+        parse_rule(const_decl, 0,
+            "FOO = 4 / 2");
+        parse_rule(const_decl, 0,
+            "FOO = 3.0 / 4.0");
+        parse_rule(const_decl, 0,
+            "FOO = 5 % 3");
+        parse_rule(const_decl, 0,
+            "FOO = 5 == 3");
+        parse_rule(const_decl, 0,
+            "FOO = 5 != 3");
         parse_rule(const_decl, 0,
-            "FOO = 1.0 * 2.0");
+            "FOO = 5 < 3");
         parse_rule(const_decl, 0,
-            "FOO = 1 / 2");
+            "FOO = 5 <= 3");
         parse_rule(const_decl, 0,
-            "FOO = 1.0 / 2.0");
+            "FOO = 5 > 3");
         parse_rule(const_decl, 0,
-            "FOO = 1 % 2");
+            "FOO = 5 >= 3");
     }
 }
 #endif