]> git.mdlowis.com Git - proto/obnc.git/commitdiff
rearranged grammar to minimize need for forward declarations
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 21 Apr 2021 17:55:34 +0000 (13:55 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 21 Apr 2021 17:55:34 +0000 (13:55 -0400)
cerise/cerise.h
cerise/codegen.c
cerise/examples/square.c [new file with mode: 0644]
cerise/oberon0/OSG.Mod
cerise/parser.c

index 66cfdcf65842eb3bb05516223763d48557a21af3..08df7ebb6dfed204a6acc007cc55211367f87a5b 100644 (file)
@@ -125,7 +125,6 @@ typedef struct {
 void lexfile(Parser* ctx, char* path);
 void lex(Parser* ctx);
 void lexprintpos(Parser* p, FILE* file, Tok* tok);
-void gettoken(Parser* ctx);
 void module(Parser* p, Item* item);
 
 /* Code Generation
@@ -136,9 +135,10 @@ 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(long long localsz);
+void codegen_endproc(void);
 
 /* Option Parsing
  *****************************************************************************/
index 6858e81d5c5bfc7513a39ebd3bae4eb6394d1078..94d831907f2d84bf1f741d2d132096819591bc9b 100644 (file)
@@ -24,11 +24,6 @@ Type StringType = {
 
 void codegen_setint(Item* item, Type* type, long long val)
 {
-    if (type == &BoolType)
-        printf("%s ", val ? "true" : "false");
-    else
-        printf("%lld ", val);
-
     item->mode = ITEM_CONST;
     item->type = type;
     item->imm.i = val;
@@ -36,8 +31,6 @@ void codegen_setint(Item* item, Type* type, long long val)
 
 void codegen_setreal(Item* item, double val)
 {
-    printf("%f ", val);
-
     item->mode = ITEM_CONST;
     item->type = &RealType;
     item->imm.f = val;
@@ -45,68 +38,11 @@ void codegen_setreal(Item* item, double val)
 
 void codegen_setstr(Item* item, char* val)
 {
-    printf("'%s' ", val);
-
     item->mode = ITEM_CONST;
     item->type = &StringType;
     item->imm.s = val;
 }
 
-/* I do not "get" this code
-  PROCEDURE MakeConstItem*(VAR x: Item; typ: Type; val: LONGINT);
-  BEGIN
-    x.mode := Const;
-    x.type := typ;
-    x.a := val
-  END MakeConstItem;
-
-  PROCEDURE negated(cond: LONGINT): LONGINT;
-  BEGIN
-    IF cond < 8 THEN
-        cond := cond+8
-    ELSE
-        cond := cond-8
-    END ;
-    RETURN cond
-  END negated;
-
-  PROCEDURE Not*(VAR x: Item);   (* x := ~x *)
-    VAR t: LONGINT;
-  BEGIN
-    IF x.mode # Cond THEN loadCond(x) END ;
-    x.r := negated(x.r);
-    t := x.a;
-    x.a := x.b;
-    x.b := t
-  END Not;
-
-
-  PROCEDURE MulOp*(VAR x, y: Item);   (* x := x * y *)
-  BEGIN
-    IF (x.mode = Const) & (y.mode = Const) THEN
-        x.a := x.a * y.a
-    ELSIF (y.mode = Const) & (y.a = 2) THEN
-        load(x);
-        Put1(Lsl, x.r, x.r, 1)
-    ELSIF y.mode = Const THEN
-        load(x);
-        Put1(Mul, x.r, x.r, y.a)
-    ELSIF x.mode = Const THEN
-        load(y);
-        Put1(Mul, y.r, y.r, x.a);
-        x.mode := Reg;
-        x.r := y.r
-    ELSE
-        load(x);
-        load(y);
-        Put0(Mul, RH-2, x.r, y.r);
-        DEC(RH);
-        x.r := RH-1
-    END
-  END MulOp;
-
-*/
-
 static int items_const(Item* a, Item* b)
 {
     return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
@@ -126,40 +62,40 @@ static void const_binop(int op, Item* a, Item* b)
             case AND: a->imm.i = a->imm.i && b->imm.i; break;
             case OR:  a->imm.i = a->imm.i || b->imm.i; break;
 
-            case EQ:  
-                a->imm.i = a->imm.i == b->imm.i; 
+            case EQ:
+                a->imm.i = a->imm.i == b->imm.i;
                 a->type = &BoolType;
                 break;
 
             case NEQ:
-                a->imm.i = a->imm.i != b->imm.i; 
+                a->imm.i = a->imm.i != b->imm.i;
                 a->type = &BoolType;
                 break;
 
             case '<':
-                a->imm.i = a->imm.i < b->imm.i; 
+                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->imm.i = a->imm.i <= b->imm.i;
                 a->type = &BoolType;
                 break;
 
             case '>':
-                a->imm.i = a->imm.i > b->imm.i; 
+                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->imm.i = a->imm.i >= b->imm.i;
                 a->type = &BoolType;
                 break;
 
 //            case IS:    break;
 
-            default: 
-                assert(!"not a valid op");       
+            default:
+                assert(!"not a valid op");
                 break;
         }
     }
@@ -172,38 +108,38 @@ static void const_binop(int op, Item* a, Item* b)
             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; 
+            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->imm.f = a->imm.f != b->imm.f;
                 a->type = &BoolType;
                 break;
 
             case '<':
-                a->imm.f = a->imm.f < b->imm.f; 
+                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->imm.f = a->imm.f <= b->imm.f;
                 a->type = &BoolType;
                 break;
 
             case '>':
-                a->imm.f = a->imm.f > b->imm.f; 
+                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->imm.f = a->imm.f >= b->imm.f;
                 a->type = &BoolType;
                 break;
 
-            default:  
-                assert(!"not a valid op");       
+            default:
+                assert(!"not a valid op");
                 break;
         }
     }
@@ -270,3 +206,16 @@ void codegen_binop(int op, Item* a, Item* b)
         assert(!"not supported");
     }
 }
+
+void codegen_startproc(long long localsz)
+{
+    printf("    pushq    rbp\n");
+    printf("    movq     rsp, rbp\n");
+    printf("    sub      $%lld, rsp\n", localsz);
+}
+
+void codegen_endproc(void)
+{
+    printf("    pop      rbp");
+    printf("    ret");
+}
diff --git a/cerise/examples/square.c b/cerise/examples/square.c
new file mode 100644 (file)
index 0000000..751e42a
--- /dev/null
@@ -0,0 +1,5 @@
+// Type your code here, or load an example.
+int square(int num) {
+    volatile int foo[4];
+    return num * num;
+}
index f7c15dd79fba7fae351f781bdde271dd764e4042..f54a5c113eb8260ee6f11ed29104c81112d40ed4 100644 (file)
@@ -432,7 +432,11 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX  9.5.2017*)
   END Open;\r
 \r
   PROCEDURE Header*(size: LONGINT);\r
-  BEGIN entry := pc*4; Put1(Sub, SP, SP, 4); Put2(Stw, LNK, SP, 0); invalSB\r
+  BEGIN\r
+    entry := pc*4;\r
+    Put1(Sub, SP, SP, 4);\r
+    Put2(Stw, LNK, SP, 0);\r
+    invalSB\r
   END Header;\r
 \r
   PROCEDURE MakeFileName(VAR FName: OSS.Ident; name, ext: ARRAY OF CHAR);\r
index bdebddbb617c21488bb41f8434e4f44905990b68..a5a9f697f479ae87ab820a94ef4a1bc9482740f7 100644 (file)
         void name(Parser* p, Item* item)
 #endif
 
+/* Default Symbols
+ *****************************************************************************/
+static Symbol BoolSym = {
+    .class = SYM_TYPE,
+    .name  = "Bool",
+    .type  = &BoolType
+};
+
+static Symbol IntSym = {
+    .next  = &BoolSym,
+    .class = SYM_TYPE,
+    .name  = "Int",
+    .type  = &IntType
+};
+
+static Symbol RealSym = {
+    .next  = &IntSym,
+    .class = SYM_TYPE,
+    .name  = "Real",
+    .type  = &RealType
+};
+
 /* Parsing Routines
  *****************************************************************************/
 static Tok* peek(Parser* p)
@@ -195,179 +217,144 @@ static void check_bool2(Parser* p, Item* a, Item* b)
 
 /* Grammar Definition
  *****************************************************************************/
-void module(Parser* p, Item* item);
-void import_list(Parser* p, Item* item);
-void declaration_seq(Parser* p, Item* item);
-void statement_seq(Parser* p, Item* item);
-void const_decl(Parser* p, Item* item);
-void expression(Parser* p, Item* item);
-void simple_expr(Parser* p, Item* item);
-void term(Parser* p, Item* item);
-void factor(Parser* p, Item* item);
-void designator(Parser* p, Item* item);
-void qualident(Parser* p, Item* item);
-void expr_list(Parser* p, Item* item);
 
-RULE(module)
-{
-    expect(p, MODULE);
-    char* sname = expect_text(p, IDENT);
-        /* TODO: Check that it matches filename here */
-    expect(p, ';');
-    if (matches(p, IMPORT))
-    {
-        import_list(p, item);
-    }
-    declaration_seq(p, item);
-    if (accept(p, BEGIN))
-    {
-        statement_seq(p, item);
-    }
-    expect(p, END);
-    char* ename = expect_text(p, IDENT);
-    if (strcmp(sname, ename))
-    {
-        error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
-    }
-    expect(p, ';');
-}
+static void expression(Parser* p, Item* item);
 
-RULE(import_list)
-{
-    (void)item;
-    expect(p, IMPORT);
-    while (1)
-    {
-        expect(p, IDENT);
-        if (accept(p, '='))
-        {
-            expect(p, IDENT);
-        }
-        if (matches(p, ';'))
-        {
-            break;
-        }
-        expect(p, ',');
-    }
-    expect(p, ';');
-}
+//RULE(expr_list)
+//{
+//    while (1)
+//    {
+//        expression(p);
+//        if (!accept(p, ','))
+//        {
+//            break;
+//        }
+//    }
+//}
 
-RULE(declaration_seq)
+RULE(qualident)
 {
-    if (accept(p, CONST))
-    {
-        const_decl(p, item);
-        expect(p, ';');
-    }
-    if (accept(p, TYPE))
-    {
-//        type_decl(p, item);
-        expect(p, ';');
-    }
-    if (accept(p, VAR))
+    char* name = expect_text(p, IDENT);
+    Symbol* sym = symbol_get(p, name);
+
+    if (sym->class == SYM_CONST)
     {
-//        var_decl(p, item);
-        expect(p, ';');
+        item->mode = ITEM_CONST;
+        item->imm = sym->imm;
     }
+//    if (accept(p, '.'))
+//    {
+//        expect(p, IDENT);
+//    }
 }
 
-RULE(statement_seq)
+RULE(designator)
 {
-    (void)p, (void)item;
+    qualident(p, item);
+//    /* selector */
+//    switch ((int)peek(p)->type)
+//    {
+//        case '.':
+//            expect(p, IDENT);
+//            break;
+//
+//        case '[':
+//            expr_list(p);
+//            expect(p, ']');
+//            break;
+//
+//        case '^':
+//            expect(p, '^');
+//            break;
+//
+//        case '(':
+//            qualident(p);
+//            expect(p, ')');
+//            break;
+//    }
 }
 
-RULE(const_decl)
+RULE(factor)
 {
-/*
-    VAR
-        obj, first: OSG.Object;
-        x: OSG.Item;
-        tp: OSG.Type;
-        L: LONGINT;
-
-    (* ... *)
-
-      WHILE sym = OSS.ident DO
-        NewObj(obj, OSG.Const);
-        OSS.Get(sym);
-        IF sym = OSS.eql THEN
-            OSS.Get(sym)
-        ELSE
-            OSS.Mark("=?")
-        END;
-        expression(x);
-        IF x.mode = OSG.Const THEN
-            obj.val := x.a;
-            obj.type := x.type
-        ELSE
-            OSS.Mark("expression not constant")
-        END ;
-        Check(OSS.semicolon, "; expected")
-      END
-*/
+    switch ((int)peek(p)->type)
+    {
+        case INT:
+            codegen_setint(item, &IntType, peek(p)->value.integer);
+            consume(p);
+            break;
 
+        case REAL:
+            codegen_setreal(item, peek(p)->value.floating);
+            consume(p);
+            break;
 
-    while (1)
-    {
-        char* name = NULL;
-        bool export = false;
-        Symbol* sym = NULL;
+        case STRING:
+            codegen_setstr(item, peek(p)->text);
+            consume(p);
+            break;
 
-        name = expect_text(p, IDENT);
-        export = accept(p, '*');
-        sym = symbol_new(p, name, SYM_CONST, export);
-        expect(p, '=');
-        expression(p, item);
+//        case NIL:
+//            codegen_nil(item);
+//            consume(p);
+//            break;
 
-        sym->imm = item->imm;
-        (void)sym;
+        case BOOL:
+            codegen_setint(item, &BoolType, peek(p)->value.integer);
+            consume(p);
+            break;
 
-        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);
-        }
+        case '(':
+            expect(p, '(');
+            expression(p, item);
+            expect(p, ')');
+            break;
 
-        if (!accept(p, ','))
-        {
+        case NOT:
+            consume(p);
+            factor(p, item);
+            check_bool(p, item);
+            codegen_unop(NOT, item);
+            break;
+
+        case IDENT:
+            designator(p, item);
+//            actual_params(p);
             break;
-        }
     }
 }
 
-RULE(expression)
+RULE(term)
 {
-    // expression = SimpleExpression [relation SimpleExpression].
-    //     relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
+    factor(p, item);
 
-    int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
-    simple_expr(p, item);
-    if (matches_oneof(p, ops))
+    while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
     {
         Item right = { 0 };
         int op = consume(p);
-        simple_expr(p, &right);
-        check_num2(p, item, &right);
-        codegen_binop(op, item, &right);
+        factor(p, &right);
+        switch(op)
+        {
+            case '*':
+            case '/':
+            case '%':
+                check_num2(p, item, &right);
+                codegen_binop(op, item, &right);
+                break;
+
+            case AND:
+                check_bool2(p, item, &right);
+                codegen_binop(op, item, &right);
+                break;
+
+            default:
+                assert(!"not supported");
+                break;
+        }
     }
 }
 
 RULE(simple_expr)
 {
-    // SimpleExpression = ["+" | "-"] term {AddOperator term}.
-    //     AddOperator = "+" | "-" | "or".
-
     /* first term and +/- */
     if (matches_oneof(p, (int[]){'+', '-', 0}))
     {
@@ -399,166 +386,121 @@ RULE(simple_expr)
     }
 }
 
-RULE(term)
+RULE(expression)
 {
-    // term = factor {MulOperator factor}.
-    //     MulOperator = "*" | "/" | "and".
-    factor(p, item);
-    while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
+    int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
+    simple_expr(p, item);
+    if (matches_oneof(p, ops))
     {
         Item right = { 0 };
         int op = consume(p);
-        factor(p, &right);
-        switch(op)
-        {
-            case '*':
-                check_num2(p, item, &right);
-                codegen_binop(op, item, &right);
-                break;
-
-            case '/':
-                check_num2(p, item, &right);
-                codegen_binop(op, item, &right);
-                break;
-
-            case '%':
-                check_int2(p, item, &right);
-                codegen_binop(op, item, &right);
-                break;
-
-            case AND:
-                check_bool2(p, item, &right);
-                codegen_binop(op, item, &right);
-                break;
-
-            default:
-                assert(!"not supported");
-                break;
-        }
+        simple_expr(p, &right);
+        check_num2(p, item, &right);
+        codegen_binop(op, item, &right);
     }
 }
 
-/*
-factor = number
-       | string
-       | "nil"
-       | "true"
-       | "false"
-       | designator [ActualParameters]
-       | "(" expression ")"
-       | "not" factor.
-*/
-
-RULE(factor)
+RULE(var_decl)
 {
-    switch ((int)peek(p)->type)
-    {
-        case INT:
-            codegen_setint(item, &IntType, peek(p)->value.integer);
-            consume(p);
-            break;
-
-        case REAL:
-            codegen_setreal(item, peek(p)->value.floating);
-            consume(p);
-            break;
-
-        case STRING:
-            codegen_setstr(item, peek(p)->text);
-            consume(p);
-            break;
-
-//        case NIL:
-//            codegen_nil(item);
-//            consume(p);
-//            break;
+    (void)p, (void)item;
+}
 
-        case BOOL:
-            codegen_setint(item, &BoolType, peek(p)->value.integer);
-            consume(p);
-            break;
+RULE(type_decl)
+{
+    (void)p, (void)item;
+}
 
-        case '(':
-            expect(p, '(');
-            expression(p, item);
-            expect(p, ')');
-            break;
+RULE(const_decl)
+{
+    while (1)
+    {
+        char* name = NULL;
+        bool export = false;
+        Symbol* sym = NULL;
 
-        case NOT:
-            consume(p);
-            factor(p, item);
-            check_bool(p, item);
-            codegen_unop(NOT, item);
-            break;
+        name = expect_text(p, IDENT);
+        export = accept(p, '*');
+        sym = symbol_new(p, name, SYM_CONST, export);
+        expect(p, '=');
+        expression(p, item);
+        sym->imm = item->imm;
 
-        case IDENT:
-            designator(p, item);
-//            actual_params(p);
+        if (!accept(p, ','))
+        {
             break;
+        }
     }
 }
 
-/*
-    designator = qualident {selector}.
-    selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
-    ExpList = expression {"," expression}.
-    qualident = [ident "."] ident.
+RULE(statement_seq)
+{
+    (void)p, (void)item;
+}
 
-    ActualParameters = "(" [ExpList] ")" .
-*/
-RULE(designator)
+RULE(declaration_seq)
 {
-    qualident(p, item);
-//    /* selector */
-//    switch ((int)peek(p)->type)
-//    {
-//        case '.':
-//            expect(p, IDENT);
-//            break;
-//
-//        case '[':
-//            expr_list(p);
-//            expect(p, ']');
-//            break;
-//
-//        case '^':
-//            expect(p, '^');
-//            break;
-//
-//        case '(':
-//            qualident(p);
-//            expect(p, ')');
-//            break;
-//    }
+    if (accept(p, CONST))
+    {
+        const_decl(p, item);
+        expect(p, ';');
+    }
+    if (accept(p, TYPE))
+    {
+//        type_decl(p, item);
+        expect(p, ';');
+    }
+    if (accept(p, VAR))
+    {
+//        var_decl(p, item);
+        expect(p, ';');
+    }
 }
 
-RULE(qualident)
+RULE(import_list)
 {
-    char* name = expect_text(p, IDENT);
-    Symbol* sym = symbol_get(p, name);
+    (void)item;
+    expect(p, IMPORT);
+    while (1)
+    {
+        expect(p, IDENT);
+        if (accept(p, '='))
+        {
+            expect(p, IDENT);
+        }
+        if (matches(p, ';'))
+        {
+            break;
+        }
+        expect(p, ',');
+    }
+    expect(p, ';');
+}
 
-    if (sym->class == SYM_CONST)
+RULE(module)
+{
+    expect(p, MODULE);
+    char* sname = expect_text(p, IDENT);
+        /* TODO: Check that it matches filename here */
+    expect(p, ';');
+    if (matches(p, IMPORT))
     {
-        item->mode = ITEM_CONST;
-        item->imm = sym->imm;
+        import_list(p, item);
     }
-//    if (accept(p, '.'))
-//    {
-//        expect(p, IDENT);
-//    }
+    declaration_seq(p, item);
+    if (accept(p, BEGIN))
+    {
+        codegen_startproc(0);
+        statement_seq(p, item);
+        codegen_endproc();
+    }
+    expect(p, END);
+    char* ename = expect_text(p, IDENT);
+    if (strcmp(sname, ename))
+    {
+        error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+    }
+    expect(p, ';');
 }
-//
-//RULE(expr_list)
-//{
-//    while (1)
-//    {
-//        expression(p);
-//        if (!accept(p, ','))
-//        {
-//            break;
-//        }
-//    }
-//}
 
 /* Grammar Unit Tests
  *****************************************************************************/
@@ -567,9 +509,10 @@ RULE(qualident)
 
 Parser Ctx = {0};
 
-void parse_init(char* fname, char* string)
+static void parse_init(char* fname, char* string)
 {
     memset(&Ctx, 0, sizeof(Ctx));
+    Ctx.scope = &RealSym;
     LexFile* file = calloc(sizeof(LexFile), 1u);
     file->path = strdup(fname);
     file->fbeg = file->fpos = strdup(string);