]> git.mdlowis.com Git - proto/obnc.git/commitdiff
commented out a bunch of code in preparation for IR overhaul
authorMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Jun 2021 20:44:21 +0000 (16:44 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Thu, 10 Jun 2021 20:44:21 +0000 (16:44 -0400)
cerise/backend/ssa/codegen.c
cerise/inc/cerise.h
cerise/src/const_ops.c
cerise/src/grammar.c
cerise/tests/Module.m

index 1ddc6db8e18ebe5138282a07d7233b83d1699fff..056efd7300dc3d629f856ae84f82942831c55656 100644 (file)
@@ -21,207 +21,207 @@ Type StringType = {
     .form = FORM_STRING,
     .size = -1
 };
-
-
-static size_t MaxBlocks = 0;
-static size_t NumBlocks = 0;
-static Block* Blocks = NULL;
-static size_t Level = 0;
-static struct {
-    size_t curr;
-    size_t join;
-} Levels[32] = {0};
-
-static size_t block_new(void)
-{
-    if (NumBlocks == MaxBlocks)
-    {
-        MaxBlocks = (MaxBlocks ? 16u : (MaxBlocks << 1u));
-        Blocks = realloc(Blocks, MaxBlocks * sizeof(Block));
-    }
-    memset(&Blocks[NumBlocks], 0, sizeof(Block));
-    NumBlocks++;
-    return (NumBlocks-1);
-}
-
-static void put_op(Operation* op)
-{
-    Block* block = &Blocks[Levels[Level].curr];
-    if (block->nops == block->mops)
-    {
-        block->mops = (block->mops ? 4u : (block->mops << 1u));
-        block->ops = realloc(block->ops, block->mops * sizeof(Operation));
-    }
-    block->ops[block->nops++] = *op;
-}
-
-static void load_var(Parser* p, Item* item)
-{
-    if (!item->reg)
-    {
-        switch (item->mode)
-        {
-            case ITEM_CONST:
-                /* TODO: range check the constant */
-                item->reg = p->curr_reg++;
-                printf("    $%d = %lld;\n", item->reg, item->imm.i);
-                break;
-
-//            case ITEM_VAR:
-//                item->reg = declare_temp(p, item->type, isref);
-//                if (item->type->form == FORM_RECORD)
-//                {
-//                    printf(" = (Byte*)&%s[0];\n", item->imm.s);
-//                }
-//                else
-//                {
-//                    printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
-//                }
-//                item->imm.i = 0;
-//                break;
 //
-//            case ITEM_MVAR:
-//                item->reg = declare_temp(p, item->type, isref);
-//                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);
-//                }
-//                item->imm.i = 0;
+//
+//static size_t MaxBlocks = 0;
+//static size_t NumBlocks = 0;
+//static Block* Blocks = NULL;
+//static size_t Level = 0;
+//static struct {
+//    size_t curr;
+//    size_t join;
+//} Levels[32] = {0};
+//
+//static size_t block_new(void)
+//{
+//    if (NumBlocks == MaxBlocks)
+//    {
+//        MaxBlocks = (MaxBlocks ? 16u : (MaxBlocks << 1u));
+//        Blocks = realloc(Blocks, MaxBlocks * sizeof(Block));
+//    }
+//    memset(&Blocks[NumBlocks], 0, sizeof(Block));
+//    NumBlocks++;
+//    return (NumBlocks-1);
+//}
+//
+//static void put_op(Operation* op)
+//{
+//    Block* block = &Blocks[Levels[Level].curr];
+//    if (block->nops == block->mops)
+//    {
+//        block->mops = (block->mops ? 4u : (block->mops << 1u));
+//        block->ops = realloc(block->ops, block->mops * sizeof(Operation));
+//    }
+//    block->ops[block->nops++] = *op;
+//}
+//
+//static void load_var(Parser* p, Item* item)
+//{
+//    if (!item->reg)
+//    {
+//        switch (item->mode)
+//        {
+//            case ITEM_CONST:
+//                /* TODO: range check the constant */
+//                item->reg = p->curr_reg++;
+//                printf("    $%d = %lld;\n", item->reg, item->imm.i);
 //                break;
-
-            default:
-                assert(!"bad load_var()");
-        }
-    }
-}
-
-
-
-
-void codegen_startmod(Parser* p)
-{
-    (void)p;
-}
-
-void codegen_endmod(Parser* p)
-{
-    (void)p;
-}
-
-void codegen_setint(Item* item, Type* type, long long val)
-{
-    item->mode  = ITEM_CONST;
-    item->type  = type;
-    item->reg   = 0;
-    item->imm.i = val;
-}
-
-void codegen_setreal(Item* item, double val)
-{
-    item->mode  = ITEM_CONST;
-    item->type  = &RealType;
-    item->reg   = 0;
-    item->imm.f = val;
-}
-
-void codegen_setstr(Item* item, char* val)
-{
-    item->mode  = ITEM_CONST;
-    item->type  = &StringType;
-    item->reg   = 0;
-    item->imm.s = val;
-}
-
-void codegen_imports(Parser* p)
-{
-    (void)p;
-}
-
-void codegen_var(Parser* p, Symbol* sym)
-{
-    (void)p, (void)sym;
-}
-
-void codegen_main(Parser* p)
-{
-    (void)p;
-}
-
-void codegen_startproc(Parser* p, Symbol* proc)
-{
-    (void)p, (void)proc;
-    printf("func %s(){\n", (proc ? proc->name : p->name));
-    printf("L%lu:\n", block_new());
-}
-
-void codegen_endproc(Parser* p)
-{
-    (void)p;
-    printf("}\n");
-}
-
-void codegen_unop(Parser* p, int op, Item* a)
-{
-    (void)p, (void)op, (void)a;
-}
-
-void codegen_binop(Parser* p, int op, Item* a, Item* b)
-{
-    (void)p, (void)op, (void)a, (void)b;
-}
-
-void codegen_store(Parser* p, Item* a, Item* b)
-{
-    (void)p, (void)a, (void)b;
-    load_var(p, b);
-}
-
-void codegen_if(Parser* p, Item* item)
-{
-    (void)p, (void)item;
-}
-
-void codegen_else(Parser* p, Item* item)
-{
-    (void)p, (void)item;
-}
-
-void codegen_endif(Parser* p, long elsifs, Item* item)
-{
-    (void)p, (void)elsifs, (void)item;
-}
-
-void codegen_prepcall(Parser* p, Item* item)
-{
-    (void)p, (void)item;
-}
-
-void codegen_call(Parser* p, Item* item, Item* args)
-{
-    (void)p, (void)item, (void)args;
-}
-
-void codegen_setarg(Parser* p, Item* item, bool firstarg)
-{
-    (void)p, (void)item, (void)firstarg;
-}
-
-void codegen_return(Parser* p, Item* item)
-{
-    (void)p, (void)item;
-}
-
-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;
-}
-
+//
+////            case ITEM_VAR:
+////                item->reg = declare_temp(p, item->type, isref);
+////                if (item->type->form == FORM_RECORD)
+////                {
+////                    printf(" = (Byte*)&%s[0];\n", item->imm.s);
+////                }
+////                else
+////                {
+////                    printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s);
+////                }
+////                item->imm.i = 0;
+////                break;
+////
+////            case ITEM_MVAR:
+////                item->reg = declare_temp(p, item->type, isref);
+////                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);
+////                }
+////                item->imm.i = 0;
+////                break;
+//
+//            default:
+//                assert(!"bad load_var()");
+//        }
+//    }
+//}
+//
+//
+//
+//
+//void codegen_startmod(Parser* p)
+//{
+//    (void)p;
+//}
+//
+//void codegen_endmod(Parser* p)
+//{
+//    (void)p;
+//}
+//
+//void codegen_setint(Item* item, Type* type, long long val)
+//{
+//    item->mode  = ITEM_CONST;
+//    item->type  = type;
+//    item->reg   = 0;
+//    item->imm.i = val;
+//}
+//
+//void codegen_setreal(Item* item, double val)
+//{
+//    item->mode  = ITEM_CONST;
+//    item->type  = &RealType;
+//    item->reg   = 0;
+//    item->imm.f = val;
+//}
+//
+//void codegen_setstr(Item* item, char* val)
+//{
+//    item->mode  = ITEM_CONST;
+//    item->type  = &StringType;
+//    item->reg   = 0;
+//    item->imm.s = val;
+//}
+//
+//void codegen_imports(Parser* p)
+//{
+//    (void)p;
+//}
+//
+//void codegen_var(Parser* p, Symbol* sym)
+//{
+//    (void)p, (void)sym;
+//}
+//
+//void codegen_main(Parser* p)
+//{
+//    (void)p;
+//}
+//
+//void codegen_startproc(Parser* p, Symbol* proc)
+//{
+//    (void)p, (void)proc;
+//    printf("func %s(){\n", (proc ? proc->name : p->name));
+//    printf("L%lu:\n", block_new());
+//}
+//
+//void codegen_endproc(Parser* p)
+//{
+//    (void)p;
+//    printf("}\n");
+//}
+//
+//void codegen_unop(Parser* p, int op, Item* a)
+//{
+//    (void)p, (void)op, (void)a;
+//}
+//
+//void codegen_binop(Parser* p, int op, Item* a, Item* b)
+//{
+//    (void)p, (void)op, (void)a, (void)b;
+//}
+//
+//void codegen_store(Parser* p, Item* a, Item* b)
+//{
+//    (void)p, (void)a, (void)b;
+//    load_var(p, b);
+//}
+//
+//void codegen_if(Parser* p, Item* item)
+//{
+//    (void)p, (void)item;
+//}
+//
+//void codegen_else(Parser* p, Item* item)
+//{
+//    (void)p, (void)item;
+//}
+//
+//void codegen_endif(Parser* p, long elsifs, Item* item)
+//{
+//    (void)p, (void)elsifs, (void)item;
+//}
+//
+//void codegen_prepcall(Parser* p, Item* item)
+//{
+//    (void)p, (void)item;
+//}
+//
+//void codegen_call(Parser* p, Item* item, Item* args)
+//{
+//    (void)p, (void)item, (void)args;
+//}
+//
+//void codegen_setarg(Parser* p, Item* item, bool firstarg)
+//{
+//    (void)p, (void)item, (void)firstarg;
+//}
+//
+//void codegen_return(Parser* p, Item* item)
+//{
+//    (void)p, (void)item;
+//}
+//
+//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 716389a8149936ee627d4ed991d8e37821e0eb41..ce835a5f3b008ffb4ed073522197a4f7ef2ea88d 100644 (file)
@@ -141,7 +141,7 @@ typedef struct {
     Tok tok;
     Module* imports;
     char* name;
-    int curr_reg;
+    long curr_reg;
     size_t msyms;
     size_t nsyms;
     Symbol* syms;
@@ -229,15 +229,20 @@ 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);
 
+enum {
+    IR_CONST
+};
+
 typedef union {
     long i;
     double f;
     char* s;
 } Operand;
 
-typedef struct {
+typedef struct Operation {
+//    struct Operation* next;
     int code : 28;
-    int type : 4;
+    int mode : 4;
     union {
         Operand args[3];
         struct {
index eedd955d139d893315cc2dcd7f1a8eebbb8c83c0..532f8f33cc7a30b989517168d657b1d837599ad7 100644 (file)
 #include "cerise.h"
-
-int items_const(Item* a, Item* b)
-{
-    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
-}
-
-void const_binop(int op, Item* a, Item* b)
-{
-    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;
-
-            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->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)
-    {
-        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 a valid form");
-    }
-}
-
-void const_unop(Parser* p, int op, Item* a)
-{
-    (void)p;
-    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)
-    {
-        switch (op)
-        {
-            case NOT: a->imm.i = !a->imm.i;      break;
-            default:  assert(!"not a valid op"); break;
-        }
-    }
-    else
-    {
-        assert(!"not a valid form");
-    }
-}
+//
+//int items_const(Item* a, Item* b)
+//{
+//    return ((a->mode == ITEM_CONST) && (b->mode == ITEM_CONST));
+//}
+//
+//void const_binop(int op, Item* a, Item* b)
+//{
+//    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;
+//
+//            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->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)
+//    {
+//        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 a valid form");
+//    }
+//}
+//
+//void const_unop(Parser* p, int op, Item* a)
+//{
+//    (void)p;
+//    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)
+//    {
+//        switch (op)
+//        {
+//            case NOT: a->imm.i = !a->imm.i;      break;
+//            default:  assert(!"not a valid op"); break;
+//        }
+//    }
+//    else
+//    {
+//        assert(!"not a valid form");
+//    }
+//}
index d90d4b9656c591fa7a0b8b021854c8a5b55df116..812f8c9a1dcb67844b62232a94e669fb99c98e7b 100644 (file)
 //#define TRACE
 #ifdef TRACE
     static int Indent = 0;
-    #define RULE(name) \
-        static void name##_actual(Parser* p, Item* item); \
-        static void name(Parser* p, Item* item) { \
-            printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \
-            name##_actual(p, item); \
-            Indent--; } \
-        static void name##_actual(Parser* p, Item* item)
+    #define ENTER_RULE() \
+        printf("%*c-> %s\n", ++Indent * 2, ' ', __func__)
+
+    #define EXIT_RULE() \
+        Indent--
 #else
-    #define RULE(name) \
-        static void name(Parser* p, Item* item)
+    #define ENTER_RULE() ((void)0)
+    #define EXIT_RULE() ((void)0)
 #endif
 
-/* Item Handling
+/* Basic Blocks and Operations
  *****************************************************************************/
-static void init_item(Item* item, Symbol* sym)
+#define MAX_OPS (256)
+static size_t NumOps = 0;
+static Operation* Ops[MAX_OPS] = {0};
+
+static void print_op(Operation* op)
 {
-    item->type = sym->type;
-    if (SYM_VAR == sym->class)
+    switch (op->code)
     {
-        item->mode = (sym->global ? ITEM_MVAR : ITEM_VAR);
-        item->imm.s = sym->name;
+        case INT:
+        case BOOL:
+            printf("    $%ld = %ld\n", op->u.args[0].i, op->u.args[1].i);
+            break;
+
+        case REAL:
+            printf("    $%ld = %f\n", op->u.args[0].i, op->u.args[1].f);
+            break;
     }
-    else if (SYM_PROC == sym->class)
+}
+
+/* Intermediate Representation
+ *****************************************************************************/
+//void codegen_startproc(Parser* p, Symbol* func);
+//void codegen_endproc(Parser* p);
+//void codegen_unop(Parser* p, int op, Item* a);
+//void codegen_binop(Parser* p, int op, Item* a, Item* b);
+//void codegen_store(Parser* p, Item* a, Item* b);
+//void codegen_if(Parser* p, Item* item);
+//void codegen_else(Parser* p, Item* item);
+//void codegen_endif(Parser* p, long elsifs, Item* item);
+//void codegen_prepcall(Parser* p, Item* item);
+//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);
+
+static Operation* ir_pop(void)
+{
+    assert(NumOps > 0);
+    return Ops[--NumOps];
+}
+
+static void ir_push(Operation* op)
+{
+    assert(NumOps < MAX_OPS);
+    Ops[NumOps++] = op;
+}
+
+static void ir_int(Parser* p, long val)
+{
+    Operation* op = calloc(1, sizeof(Operation));
+    op->code = INT;
+    op->mode = IR_CONST;
+    op->u.args[0].i = p->curr_reg++;
+    op->u.args[1].i = val;
+    print_op(op);
+    ir_push(op);
+}
+
+static void ir_real(Parser* p, double val)
+{
+    Operation* op = calloc(1, sizeof(Operation));
+    op->code = REAL;
+    op->mode = IR_CONST;
+    op->u.args[0].i = p->curr_reg++;
+    op->u.args[1].f = val;
+    print_op(op);
+    ir_push(op);
+}
+
+static void ir_getconst(Parser* p, Symbol* sym)
+{
+    Operation* op = ir_pop();
+    if (op->mode != IR_CONST)
+    {
+        error(p, "Constant definition is non-constant");
+    }
+//    sym->type = op->type;
+    if (op->code == INT)
+    {
+        sym->imm.i = op->u.args[1].i;
+    }
+    else
+    {
+        sym->imm.i = op->u.args[1].f;
+    }
+}
+
+static void ir_unop(Parser* p, int op)
+{
+    Operation* a = ir_pop();
+    if (a->mode == IR_CONST)
     {
-        item->mode = ITEM_MVAR;
-        item->imm.s = sym->name;
+        if (a->code == INT)
+        {
+            switch (op)
+            {
+                case '+': a->u.args[1].i = +a->u.args[1].i; break;
+                case '-': a->u.args[1].i = -a->u.args[1].i; break;
+                default:  assert(!"not a valid op");    break;
+            }
+        }
+        else if (a->code == REAL)
+        {
+            switch (op)
+            {
+                case '+': a->u.args[1].f = +a->u.args[1].f; break;
+                case '-': a->u.args[1].f = -a->u.args[1].f; break;
+                default:  assert(!"not a valid op");    break;
+            }
+        }
+        else if (a->code == BOOL)
+        {
+            switch (op)
+            {
+                case NOT: a->u.args[1].i = !a->u.args[1].i; break;
+                default:  assert(!"not a valid op");    break;
+            }
+        }
     }
     else
     {
-        item->mode = ITEM_CONST;
-        item->imm  = sym->imm;
+        assert(!"unimplemented unary op");
     }
+    print_op(a);
+    ir_push(a);
 }
 
+/* Item Handling
+ *****************************************************************************/
 Field* add_field(Parser* p, Type* type, char* name, bool export)
 {
     Field* prev = NULL;
@@ -73,403 +181,428 @@ Field* add_field(Parser* p, Type* type, char* name, bool export)
 
 /* Grammar Definition
  *****************************************************************************/
-static void expression(Parser* p, Item* item);
-
-RULE(qualident)
-{
-    char* name = expect_text(p, IDENT);
-    Symbol* sym = symbol_get(p, name, -1);
-    init_item(item, sym);
-
-//    if (accept(p, '.'))
+static void expression(Parser* p);
+
+//RULE(qualident, Item* item)
+//{
+//    ENTER_RULE();
+//    char* name = expect_text(p, IDENT);
+//    Symbol* sym = symbol_get(p, name, -1);
+//    init_item(item, sym);
+//    (void)sym;
+//
+////    if (accept(p, '.'))
+////    {
+////        expect(p, IDENT);
+////    }
+//    EXIT_RULE();
+//}
+//
+//RULE(designator, Item* item)
+//{
+//    ENTER_RULE();
+//    qualident(p, item);
+//    /* selector */
+//    for (int done = 0; !done;)
 //    {
-//        expect(p, IDENT);
+//        switch ((int)peek(p)->type)
+//        {
+//            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 '[':
+//            {
+//                Item index = {0};
+//                expect(p, '[');
+//                expression(p, &index);
+//                if (item->type->form == FORM_ARRAY)
+//                {
+//                    codegen_index(p, item, &index);
+//                }
+//                else
+//                {
+//                    error(p, "attempting to index non-array value");
+//                }
+//                expect(p, ']');
+//                break;
+//            }
+//
+//    //        case '^':
+//    //            expect(p, '^');
+//    //            break;
+//
+//    //        case '(':
+//    //            qualident(p);
+//    //            expect(p, ')');
+//    //            break;
+//
+//            default:
+//                done = 1;
+//                break;
+//        }
 //    }
-}
+//    EXIT_RULE();
+//}
 
-RULE(designator)
-{
-    qualident(p, item);
-    /* selector */
-    for (int done = 0; !done;)
-    {
-        switch ((int)peek(p)->type)
-        {
-            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 '[':
-            {
-                Item index = {0};
-                expect(p, '[');
-                expression(p, &index);
-                if (item->type->form == FORM_ARRAY)
-                {
-                    codegen_index(p, item, &index);
-                }
-                else
-                {
-                    error(p, "attempting to index non-array value");
-                }
-                expect(p, ']');
-                break;
-            }
-
-    //        case '^':
-    //            expect(p, '^');
-    //            break;
-
-    //        case '(':
-    //            qualident(p);
-    //            expect(p, ')');
-    //            break;
-
-            default:
-                done = 1;
-                break;
-        }
-    }
-}
-
-RULE(factor)
+static void factor(Parser* p)
 {
+    ENTER_RULE();
     switch ((int)peek(p)->type)
     {
         case INT:
-            codegen_setint(item, &IntType, peek(p)->value.integer);
+            ir_int(p, peek(p)->value.integer);
             consume(p);
             break;
 
         case REAL:
-            codegen_setreal(item, peek(p)->value.floating);
+            ir_real(p, peek(p)->value.floating);
             consume(p);
             break;
 
-        case STRING:
-            codegen_setstr(item, peek(p)->text);
-            consume(p);
-            break;
-
-//        case NIL:
-//            codegen_nil(item);
+//        case STRING:
+//            codegen_setstr(item, peek(p)->text);
 //            consume(p);
 //            break;
 
         case BOOL:
-            codegen_setint(item, &BoolType, peek(p)->value.integer);
+            ir_int(p, peek(p)->value.integer);
             consume(p);
             break;
 
-        case '(':
-            expect(p, '(');
-            expression(p, item);
-            expect(p, ')');
-            break;
+//        case '(':
+//            expect(p, '(');
+//            expression(p, item);
+//            expect(p, ')');
+//            break;
 
-        case NOT:
-            consume(p);
-            factor(p, item);
-            check_bool(p, item);
-            codegen_unop(p, NOT, item);
-            break;
+//        case NOT:
+//            consume(p);
+//            factor(p, item);
+//            check_bool(p, item);
+//            codegen_unop(p, NOT, item);
+//            break;
 
-        case IDENT:
-            designator(p, item);
-            if (accept(p, '('))
-            {
-                Symbol* proc = symbol_get(p, item->imm.s, SYM_PROC);
-                item->type = proc->type->base;
-                Field* args = proc->type->fields;
-                Item arglist = {0};
-                Item** currarg = &(arglist.next);
-                while (args && !matches(p, ')'))
-                {
-                    Item argdef = { .type = args->type };
-                    Item* argval = calloc(1, sizeof(Item));
-                    expression(p, argval);
-                    check_types(p, &argdef, argval);
-                    codegen_setarg(p, argval, (arglist.next == 0));
-                    *currarg = argval;
-                    currarg = &(argval->next);
-                    args = args->next;
-                    if (args)
-                    {
-                        expect(p, ',');
-                    }
-                }
-                if (args)
-                {
-                    error(p, "too few arguments to function '%s'", proc->name);
-                }
-                else if (!matches(p, ')'))
-                {
-                    bool comma = accept(p, ',');
-                    if (comma && matches(p, ')'))
-                    {
-                        error(p, "trailing comma in argument list");
-                    }
-                    else
-                    {
-                        error(p, "too many arguments to function '%s'", proc->name);
-                    }
-                }
-                codegen_call(p, item, arglist.next);
-                expect(p, ')');
-            }
-            break;
+//        case IDENT:
+//            designator(p, item);
+//            if (accept(p, '('))
+//            {
+//                Symbol* proc = symbol_get(p, item->imm.s, SYM_PROC);
+//                item->type = proc->type->base;
+//                Field* args = proc->type->fields;
+//                Item arglist = {0};
+//                Item** currarg = &(arglist.next);
+//                while (args && !matches(p, ')'))
+//                {
+//                    Item argdef = { .type = args->type };
+//                    Item* argval = calloc(1, sizeof(Item));
+//                    expression(p, argval);
+//                    check_types(p, &argdef, argval);
+//                    codegen_setarg(p, argval, (arglist.next == 0));
+//                    *currarg = argval;
+//                    currarg = &(argval->next);
+//                    args = args->next;
+//                    if (args)
+//                    {
+//                        expect(p, ',');
+//                    }
+//                }
+//                if (args)
+//                {
+//                    error(p, "too few arguments to function '%s'", proc->name);
+//                }
+//                else if (!matches(p, ')'))
+//                {
+//                    bool comma = accept(p, ',');
+//                    if (comma && matches(p, ')'))
+//                    {
+//                        error(p, "trailing comma in argument list");
+//                    }
+//                    else
+//                    {
+//                        error(p, "too many arguments to function '%s'", proc->name);
+//                    }
+//                }
+//                codegen_call(p, item, arglist.next);
+//                expect(p, ')');
+//            }
+//            break;
 
         default:
             printf("unknown factor: %d\n", peek(p)->type);
             break;
     }
+    EXIT_RULE();
 }
 
-RULE(term)
+
+static void term(Parser* p)
 {
-    factor(p, item);
+    ENTER_RULE();
 
-    while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
-    {
-        Item right = { 0 };
-        int op = consume(p);
-        factor(p, &right);
-        switch(op)
-        {
-            case '*':
-            case '/':
-            case '%':
-                check_nums(p, item, &right);
-                codegen_binop(p, op, item, &right);
-                break;
-
-            case AND:
-                check_bools(p, item, &right);
-                codegen_binop(p, op, item, &right);
-                break;
-
-            default:
-                assert(!"not supported");
-                break;
-        }
-    }
+    factor(p);
+
+//    while (matches_oneof(p, (int[]){'*', '/', '%', AND, 0}))
+//    {
+//        Item right = { 0 };
+//        int op = consume(p);
+//        factor(p, &right);
+//        switch(op)
+//        {
+//            case '*':
+//            case '/':
+//            case '%':
+//                check_nums(p, item, &right);
+//                codegen_binop(p, op, item, &right);
+//                break;
+//
+//            case AND:
+//                check_bools(p, item, &right);
+//                codegen_binop(p, op, item, &right);
+//                break;
+//
+//            default:
+//                assert(!"not supported");
+//                break;
+//        }
+//    }
+
+    EXIT_RULE();
 }
 
-RULE(simple_expr)
+static void simple_expr(Parser* p)
 {
+    ENTER_RULE();
+
     /* first term and +/- */
     if (matches_oneof(p, (int[]){'+', '-', 0}))
     {
         int op = consume(p); // OP
-        term(p, item);
-        check_num(p, item);
-        codegen_unop(p, op, item);
+        term(p);
+        ir_unop(p, op);
+//        check_num(p, item);
+//        codegen_unop(p, op, item);
     }
     else
     {
-        term(p, item);
+        term(p);
     }
 
-    /* optional second term and op */
-    while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
-    {
-        Item right = { 0 };
-        int op = consume(p);
-        term(p, &right);
-        if (op == OR)
-        {
-            check_bools(p, item, &right);
-        }
-        else
-        {
-            check_nums(p, item, &right);
-        }
-        codegen_binop(p, op, item, &right);
-    }
-}
-
-RULE(expression)
-{
-    int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
-    simple_expr(p, item);
+//    /* optional second term and op */
+//    while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
+//    {
+//        Item right = { 0 };
+//        int op = consume(p);
+//        term(p, &right);
+//        if (op == OR)
+//        {
+//            check_bools(p, item, &right);
+//        }
+//        else
+//        {
+//            check_nums(p, item, &right);
+//        }
+//        codegen_binop(p, op, item, &right);
+//    }
 
-    if (matches_oneof(p, ops))
-    {
-        Item right = { 0 };
-        int op = consume(p);
-        simple_expr(p, &right);
-        check_nums(p, item, &right);
-        codegen_binop(p, op, item, &right);
-    }
+    EXIT_RULE();
 }
 
-RULE(type)
+static void expression(Parser* p)
 {
-    (void)item;
-    if (matches(p, IDENT))
-    {
-        char* text = expect_text(p, IDENT);
-        Symbol* sym = symbol_get(p, text, SYM_TYPE);
-        item->type = sym->type;
-    }
-    else if (accept(p, ARRAY))
-    {
-        expression(p, item);
-        if (item->mode != ITEM_CONST)
-        {
-            error(p, "non-constant array size");
-        }
-        expect(p, OF);
-        Item base = {0};
-        type(p, &base);
-        item->type = calloc(1, sizeof(Type));
-        item->type->form = FORM_ARRAY;
-        item->type->size = item->imm.i;
-        item->type->base = base.type;
-    }
-    else if (accept(p, RECORD))
-    {
-        long offset = 0;
-        item->type = calloc(1, sizeof(Type));
-        item->type->form = FORM_RECORD;
+    ENTER_RULE();
+//    int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
 
-        while (peek(p)->type != END)
-        {
-            /* parse the field name list */
-            Field* first = NULL;
-            int nfields = 0;
-            do
-            {
-                char* name = expect_text(p, IDENT);
-                bool export = accept(p, '*');
-                Field* f = add_field(p, item->type, name, export);
-                nfields++;
-                if (!first)
-                {
-                    first = f;
-                }
-            }
-            while (accept(p, ','));
-
-            /* now parse the type designation */
-            Item field_type = {0};
-            expect(p, ':');
-            type(p, &field_type);
-
-            /* apply the type to the newly created symbols */
-            for (int i = 0; i < nfields; i++)
-            {
-                offset = align_item(offset, field_type.type->size);
-                first->type = field_type.type;
-                first->offset = offset;
-                offset += size_of(first->type);
-                first = first->next;
-            }
-        }
-        item->type->size = offset;
-
-        expect(p, END);
-    }
-    else
-    {
-        error(p, "expected a type");
-    }
-}
+    simple_expr(p);
 
-RULE(statement_seq)
-{
-    do
-    {
-        if (matches(p, IF))
-        {
-            expect(p, IF);
-            expression(p, item);
-            check_bool(p, item);
-            codegen_if(p, item);
-            expect(p, THEN);
-            statement_seq(p, &(Item){0});
-            int elsifs = 0;
-            while (accept(p, ELSIF))
-            {
-                elsifs++;
-                codegen_else(p, item);
-                expression(p, item);
-                check_bool(p, item);
-                codegen_if(p, item);
-                expect(p, THEN);
-                statement_seq(p, &(Item){0});
-            }
-            if (accept(p, ELSE))
-            {
-                codegen_else(p, item);
-                statement_seq(p, &(Item){0});
-            }
-            codegen_endif(p, elsifs, item);
-            expect(p, END);
-        }
-        else /* assignments/expressions */
-        {
-            expression(p, item);
-            if (accept(p, '='))
-            {
-                Item right = { 0 };
-                expression(p, &right);
-                check_types(p, item, &right);
-                codegen_store(p, item, &right);
-            }
-            expect(p, ';');
-        }
-    }
-    while (!matches(p, END) && !matches(p, ELSE) && !matches(p, ELSIF) && !matches(p, RETURN));
-}
+//    if (matches_oneof(p, ops))
+//    {
+//        Item right = { 0 };
+//        int op = consume(p);
+//        simple_expr(p, &right);
+//        check_nums(p, item, &right);
+//        codegen_binop(p, op, item, &right);
+//    }
 
-RULE(var_decl)
-{
-    (void)item;
-    do
-    {
-        char* name = expect_text(p, IDENT);
-        bool export = accept(p, '*');
-        Symbol* sym = symbol_new(p, 0, name, SYM_VAR, export);
-        Item base_type = {0};
-        expect(p, ':');
-        type(p, &base_type);
-        sym->type = base_type.type;
-    }
-    while (matches(p, IDENT));
+    EXIT_RULE();
 }
 
-RULE(type_decl)
-{
-    char* name = NULL;
-    bool export = false;
-    Symbol* sym = NULL;
+//RULE(type, Item* item)
+//{
+//    ENTER_RULE();
+//    (void)item;
+//    if (matches(p, IDENT))
+//    {
+//        char* text = expect_text(p, IDENT);
+//        Symbol* sym = symbol_get(p, text, SYM_TYPE);
+//        item->type = sym->type;
+//    }
+//    else if (accept(p, ARRAY))
+//    {
+//        expression(p, item);
+//        if (item->mode != ITEM_CONST)
+//        {
+//            error(p, "non-constant array size");
+//        }
+//        expect(p, OF);
+//        Item base = {0};
+//        type(p, &base);
+//        item->type = calloc(1, sizeof(Type));
+//        item->type->form = FORM_ARRAY;
+//        item->type->size = item->imm.i;
+//        item->type->base = base.type;
+//    }
+//    else if (accept(p, RECORD))
+//    {
+//        long offset = 0;
+//        item->type = calloc(1, sizeof(Type));
+//        item->type->form = FORM_RECORD;
+//
+//        while (peek(p)->type != END)
+//        {
+//            /* parse the field name list */
+//            Field* first = NULL;
+//            int nfields = 0;
+//            do
+//            {
+//                char* name = expect_text(p, IDENT);
+//                bool export = accept(p, '*');
+//                Field* f = add_field(p, item->type, name, export);
+//                nfields++;
+//                if (!first)
+//                {
+//                    first = f;
+//                }
+//            }
+//            while (accept(p, ','));
+//
+//            /* now parse the type designation */
+//            Item field_type = {0};
+//            expect(p, ':');
+//            type(p, &field_type);
+//
+//            /* apply the type to the newly created symbols */
+//            for (int i = 0; i < nfields; i++)
+//            {
+//                offset = align_item(offset, field_type.type->size);
+//                first->type = field_type.type;
+//                first->offset = offset;
+//                offset += size_of(first->type);
+//                first = first->next;
+//            }
+//        }
+//        item->type->size = offset;
+//
+//        expect(p, END);
+//    }
+//    else
+//    {
+//        error(p, "expected a type");
+//    }
+//    EXIT_RULE();
+//}
 
-    do
-    {
-        name = expect_text(p, IDENT);
-        export = accept(p, '*');
-        sym = symbol_new(p, 0, name, SYM_TYPE, export);
-        expect(p, '=');
-        type(p, item);
-        sym->type = item->type;
-    }
-    while (matches(p, IDENT));
-}
+//RULE(statement_seq, Item* item)
+//{
+//    ENTER_RULE();
+//    do
+//    {
+//        if (matches(p, IF))
+//        {
+//            expect(p, IF);
+//            expression(p, item);
+//            check_bool(p, item);
+//            codegen_if(p, item);
+//            expect(p, THEN);
+//            statement_seq(p, &(Item){0});
+//            int elsifs = 0;
+//            while (accept(p, ELSIF))
+//            {
+//                elsifs++;
+//                codegen_else(p, item);
+//                expression(p, item);
+//                check_bool(p, item);
+//                codegen_if(p, item);
+//                expect(p, THEN);
+//                statement_seq(p, &(Item){0});
+//            }
+//            if (accept(p, ELSE))
+//            {
+//                codegen_else(p, item);
+//                statement_seq(p, &(Item){0});
+//            }
+//            codegen_endif(p, elsifs, item);
+//            expect(p, END);
+//        }
+//        else /* assignments/expressions */
+//        {
+//            expression(p, item);
+//            if (accept(p, '='))
+//            {
+//                Item right = { 0 };
+//                expression(p, &right);
+//                check_types(p, item, &right);
+//                codegen_store(p, item, &right);
+//            }
+//            expect(p, ';');
+//        }
+//    }
+//    while (!matches(p, END) && !matches(p, ELSE) && !matches(p, ELSIF) && !matches(p, RETURN));
+//    EXIT_RULE();
+//}
+
+//RULE(var_decl, Item* item)
+//{
+//    ENTER_RULE();
+//    (void)item;
+//    do
+//    {
+//        char* name = expect_text(p, IDENT);
+//        bool export = accept(p, '*');
+//        Symbol* sym = symbol_new(p, 0, name, SYM_VAR, export);
+//        Item base_type = {0};
+//        expect(p, ':');
+//        type(p, &base_type);
+//        sym->type = base_type.type;
+//    }
+//    while (matches(p, IDENT));
+//    EXIT_RULE();
+//}
+//
+//RULE(type_decl, Item* item)
+//{
+//    ENTER_RULE();
+//    char* name = NULL;
+//    bool export = false;
+//    Symbol* sym = NULL;
+//
+//    do
+//    {
+//        name = expect_text(p, IDENT);
+//        export = accept(p, '*');
+//        sym = symbol_new(p, 0, name, SYM_TYPE, export);
+//        expect(p, '=');
+//        type(p, item);
+//        sym->type = item->type;
+//    }
+//    while (matches(p, IDENT));
+//    EXIT_RULE();
+//}
 
-RULE(const_decl)
+static void const_decl(Parser* p)
 {
+//    ENTER_RULE();
     char* name = NULL;
     bool export = false;
     Symbol* sym = NULL;
@@ -479,91 +612,94 @@ RULE(const_decl)
         name = expect_text(p, IDENT);
         export = accept(p, '*');
         sym = symbol_new(p, 0, name, SYM_CONST, export);
-
         expect(p, '=');
-        expression(p, item);
-        sym->imm = item->imm;
-        sym->type = item->type;
+        expression(p);
+        ir_getconst(p, sym);
+//        sym->imm = item->imm;
+//        sym->type = item->type;
     }
     while (matches(p, IDENT));
+//    EXIT_RULE();
 }
 
-RULE(proc_decl)
-{
-    expect(p, PROCEDURE);
-    char* name = expect_text(p, IDENT);
-    bool export = accept(p, '*');
-    Symbol* proc = symbol_new(p, 0, name, SYM_PROC, export);
-    Type* proctype = calloc(1, sizeof(Type));
-    proctype->form = FORM_PROC;
-    proc->type = proctype;
-    size_t scope = symbol_openscope(p);
-
-    /* construct the proc type */
-    expect(p, '(');
-    while (!matches(p, ')'))
-    {
-        char* name = expect_text(p, IDENT);
-        expect(p, ':');
-        type(p, item);
-        proc->nargs++;
-        add_field(p, proctype, name, false)->type = item->type;
-        symbol_new(p, scope, name, SYM_VAR, export)->type = item->type;
-        if (!matches(p, ')'))
-        {
-            expect(p, ',');
-        }
-    }
-    expect(p, ')');
-    if (accept(p, ':'))
-    {
-        type(p, item);
-        proctype->base = item->type;
-    }
-
-    codegen_startproc(p, proc);
-
-    /* parse the declarations */
-    if (accept(p, CONST))
-    {
-        const_decl(p, item);
-    }
-
-    if (accept(p, TYPE))
-    {
-        type_decl(p, item);
-    }
-
-    if (accept(p, VAR))
-    {
-        var_decl(p, item);
-    }
-
-    /* parse the body of the procedure */
-    expect(p, BEGIN);
-    if (!matches(p, RETURN) && !matches(p, END))
-    {
-        statement_seq(p, item);
-    }
-    if (accept(p, RETURN))
-    {
-        expression(p, item);
-        codegen_return(p, item);
-        expect(p, ';');
-    }
-    else
-    {
-        codegen_return(p, NULL);
-    }
-    expect(p, END);
-
-    codegen_endproc(p);
-    symbol_closescope(p, scope);
-}
-
-RULE(import_list)
+//RULE(proc_decl, Item* item)
+//{
+//    ENTER_RULE();
+//    expect(p, PROCEDURE);
+//    char* name = expect_text(p, IDENT);
+//    bool export = accept(p, '*');
+//    Symbol* proc = symbol_new(p, 0, name, SYM_PROC, export);
+//    Type* proctype = calloc(1, sizeof(Type));
+//    proctype->form = FORM_PROC;
+//    proc->type = proctype;
+//    size_t scope = symbol_openscope(p);
+//
+//    /* construct the proc type */
+//    expect(p, '(');
+//    while (!matches(p, ')'))
+//    {
+//        char* name = expect_text(p, IDENT);
+//        expect(p, ':');
+//        type(p, item);
+//        proc->nargs++;
+//        add_field(p, proctype, name, false)->type = item->type;
+//        symbol_new(p, scope, name, SYM_VAR, export)->type = item->type;
+//        if (!matches(p, ')'))
+//        {
+//            expect(p, ',');
+//        }
+//    }
+//    expect(p, ')');
+//    if (accept(p, ':'))
+//    {
+//        type(p, item);
+//        proctype->base = item->type;
+//    }
+//
+//    codegen_startproc(p, proc);
+//
+//    /* parse the declarations */
+//    if (accept(p, CONST))
+//    {
+//        const_decl(p, item);
+//    }
+//
+//    if (accept(p, TYPE))
+//    {
+//        type_decl(p, item);
+//    }
+//
+//    if (accept(p, VAR))
+//    {
+//        var_decl(p, item);
+//    }
+//
+//    /* parse the body of the procedure */
+//    expect(p, BEGIN);
+//    if (!matches(p, RETURN) && !matches(p, END))
+//    {
+//        statement_seq(p, item);
+//    }
+//    if (accept(p, RETURN))
+//    {
+//        expression(p, item);
+//        codegen_return(p, item);
+//        expect(p, ';');
+//    }
+//    else
+//    {
+//        codegen_return(p, NULL);
+//    }
+//    expect(p, END);
+//
+//    codegen_endproc(p);
+//    symbol_closescope(p, scope);
+//    EXIT_RULE();
+//}
+
+static void import_list(Parser* p)
 {
-    (void)item;
+//    ENTER_RULE();
     expect(p, IMPORT);
     do
     {
@@ -589,49 +725,51 @@ RULE(import_list)
         m->next = p->imports;
         p->imports = m;
     }
+//    EXIT_RULE();
 }
 
-RULE(module)
+static void module(Parser* p)
 {
+    ENTER_RULE();
     size_t scope = symbol_openscope(p);
 
     expect(p, MODULE);
     p->name = expect_text(p, IDENT);
-        /* TODO: Check that it matches filename here */
+    /* TODO: Check that it matches filename here */
 
     if (matches(p, IMPORT))
     {
-        import_list(p, item);
+        import_list(p);
     }
 
     if (accept(p, CONST))
     {
-        const_decl(p, item);
+        const_decl(p);
     }
 
-    if (accept(p, TYPE))
-    {
-        type_decl(p, item);
-    }
-
-    if (accept(p, VAR))
-    {
-        var_decl(p, item);
-    }
+//    if (accept(p, TYPE))
+//    {
+//        type_decl(p);
+//    }
+//
+//    if (accept(p, VAR))
+//    {
+//        var_decl(p);
+//    }
 
-    while (matches(p, PROCEDURE))
-    {
-        proc_decl(p, item);
-    }
+//    while (matches(p, PROCEDURE))
+//    {
+//        proc_decl(p);
+//    }
 
-    codegen_startproc(p, NULL);
-    if (accept(p, BEGIN))
-    {
-        codegen_imports(p);
-        statement_seq(p, item);
-        expect(p, END);
-    }
-    codegen_endproc(p);
+//    codegen_startproc(p, NULL);
+//    if (accept(p, BEGIN))
+//    {
+//        codegen_imports(p);
+//        statement_seq(p, item);
+//        expect(p, END);
+//    }
+//    codegen_endproc(p);
 
     if (!matches(p, END_FILE))
     {
@@ -639,6 +777,7 @@ RULE(module)
     }
 
     symbol_closescope(p, scope);
+    EXIT_RULE();
 }
 
 static inline char* file_load(char* path)
@@ -680,10 +819,10 @@ void compile(char* fname)
     symbol_new(p, 0, "Real",   SYM_TYPE, 0)->type = &RealType;
     symbol_new(p, 0, "String", SYM_TYPE, 0)->type = &StringType;
 
-    codegen_startmod(p);
-    module(p, &(Item){0});
-    codegen_main(p);
-    codegen_endmod(p);
+//    codegen_startmod(p);
+    module(p);
+//    codegen_main(p);
+//    codegen_endmod(p);
 }
 
 /* Grammar Unit Tests
@@ -691,112 +830,112 @@ void compile(char* fname)
 #ifdef CERISE_TESTS
 #include "atf.h"
 
-Parser Ctx = {0};
-
-static void parse_init(char* fname, char* string)
-{
-    memset(&Ctx, 0, sizeof(Ctx));
-    symbol_new(&Ctx, 0, "Bool",   SYM_TYPE, 0)->type = &BoolType;
-    symbol_new(&Ctx, 0, "Int",    SYM_TYPE, 0)->type = &IntType;
-    symbol_new(&Ctx, 0, "Real",   SYM_TYPE, 0)->type = &RealType;
-    symbol_new(&Ctx, 0, "String", SYM_TYPE, 0)->type = &StringType;
-    LexFile* file = calloc(sizeof(LexFile), 1u);
-    file->path = strdup(fname);
-    file->fbeg = file->fpos = strdup(string);
-    file->next = Ctx.file;
-    Ctx.file = file;
-}
-
-static void parse_rule(void (*rule)(Parser*, Item*), Item* item, char* string)
-{
-//    puts("");
-//    printf("%s\n", string);
-    parse_init("test_input", string);
-    rule(&Ctx, (item ? item : &(Item){0}));
-}
-
-static void parse_module(char* fname, char* string)
-{
-    parse_init(fname, string);
-    module(&Ctx, &(Item){0});
-}
+//Parser Ctx = {0};
+//
+//static void parse_init(char* fname, char* string)
+//{
+//    memset(&Ctx, 0, sizeof(Ctx));
+//    symbol_new(&Ctx, 0, "Bool",   SYM_TYPE, 0)->type = &BoolType;
+//    symbol_new(&Ctx, 0, "Int",    SYM_TYPE, 0)->type = &IntType;
+//    symbol_new(&Ctx, 0, "Real",   SYM_TYPE, 0)->type = &RealType;
+//    symbol_new(&Ctx, 0, "String", SYM_TYPE, 0)->type = &StringType;
+//    LexFile* file = calloc(sizeof(LexFile), 1u);
+//    file->path = strdup(fname);
+//    file->fbeg = file->fpos = strdup(string);
+//    file->next = Ctx.file;
+//    Ctx.file = file;
+//}
+//
+//static void parse_rule(void (*rule)(Parser*, Item*), Item* item, char* string)
+//{
+////    puts("");
+////    printf("%s\n", string);
+//    parse_init("test_input", string);
+//    rule(&Ctx, (item ? item : &(Item){0}));
+//}
+//
+//static void parse_module(char* fname, char* string)
+//{
+//    parse_init(fname, string);
+//    module(&Ctx, &(Item){0});
+//}
 
 TEST_SUITE(Grammar)
 {
-    TEST(Should parse basic module syntax)
-    {
-        parse_module("Empty", "module Empty");
-        parse_module("ModA",  "module ModA import ModB");
-        parse_module("ModA",  "module ModA const FOO = 42");
-        parse_module("ModA",  "module ModA var foo : Int");
-    }
-
-    TEST(Should parse imports)
-    {
-        parse_rule(import_list, 0, "import A;");
-        parse_rule(import_list, 0, "import A = ModA;");
-        parse_rule(import_list, 0, "import A, B;");
-        parse_rule(import_list, 0, "import A, B = ModB, C;");
-    }
-
-    TEST(Should parse constant declarations and expressions)
-    {
-        parse_rule(const_decl, 0, "FOO = 123");
-        parse_rule(const_decl, 0, "FOO = 123.123");
-        parse_rule(const_decl, 0, "FOO = \"\"");
-        parse_rule(const_decl, 0, "FOO = true");
-        parse_rule(const_decl, 0, "FOO = false");
-//        parse_rule(const_decl, 0, "FOO = nil");
-        parse_rule(const_decl, 0, "FOO = not true");
-        parse_rule(const_decl, 0, "FOO = (not false)");
-        parse_rule(const_decl, 0, "FOO = +1");
-        parse_rule(const_decl, 0, "FOO = -1");
-        parse_rule(const_decl, 0, "FOO = +1.0");
-        parse_rule(const_decl, 0, "FOO = -1.0");
-        parse_rule(const_decl, 0, "FOO = 1 + 2");
-        parse_rule(const_decl, 0, "FOO = 1.0 + 2.0");
-        parse_rule(const_decl, 0, "FOO = 1 - 2");
-        parse_rule(const_decl, 0, "FOO = 1.0 - 2.0");
-        parse_rule(const_decl, 0, "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 = 5 < 3");
-        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 = 5, BAR = FOO - 3");
-    }
-
-    TEST(Should parse module level type declarations)
-    {
-        parse_rule(type_decl, 0, "a = Int");
-        parse_rule(type_decl, 0, "a = Real");
-        parse_rule(type_decl, 0, "a = Bool");
-        parse_rule(type_decl, 0, "a = array 42 of Int");
-        parse_rule(type_decl, 0, "a = array 42 of array 42 of Int");
-        parse_rule(type_decl, 0, "a = record end");
-    }
-
-    TEST(Should parse module level variable declarations)
-    {
-        parse_rule(var_decl, 0, "i : Int");
-        parse_rule(var_decl, 0, "i : Real");
-        parse_rule(var_decl, 0, "i : Bool");
-//        parse_rule(var_decl, 0, "x,y,z : Int");
-    }
-
-    TEST(Should parse module level procedure declarations)
-    {
-        parse_rule(proc_decl, 0,
-            "procedure Foo*() : Int\n"
-            "begin\n"
-            "    return 1;\n"
-            "end"
-         );
-    }
+//    TEST(Should parse basic module syntax)
+//    {
+//        parse_module("Empty", "module Empty");
+//        parse_module("ModA",  "module ModA import ModB");
+//        parse_module("ModA",  "module ModA const FOO = 42");
+//        parse_module("ModA",  "module ModA var foo : Int");
+//    }
+//
+//    TEST(Should parse imports)
+//    {
+//        parse_rule(import_list, 0, "import A;");
+//        parse_rule(import_list, 0, "import A = ModA;");
+//        parse_rule(import_list, 0, "import A, B;");
+//        parse_rule(import_list, 0, "import A, B = ModB, C;");
+//    }
+//
+//    TEST(Should parse constant declarations and expressions)
+//    {
+//        parse_rule(const_decl, 0, "FOO = 123");
+//        parse_rule(const_decl, 0, "FOO = 123.123");
+//        parse_rule(const_decl, 0, "FOO = \"\"");
+//        parse_rule(const_decl, 0, "FOO = true");
+//        parse_rule(const_decl, 0, "FOO = false");
+////        parse_rule(const_decl, 0, "FOO = nil");
+//        parse_rule(const_decl, 0, "FOO = not true");
+//        parse_rule(const_decl, 0, "FOO = (not false)");
+//        parse_rule(const_decl, 0, "FOO = +1");
+//        parse_rule(const_decl, 0, "FOO = -1");
+//        parse_rule(const_decl, 0, "FOO = +1.0");
+//        parse_rule(const_decl, 0, "FOO = -1.0");
+//        parse_rule(const_decl, 0, "FOO = 1 + 2");
+//        parse_rule(const_decl, 0, "FOO = 1.0 + 2.0");
+//        parse_rule(const_decl, 0, "FOO = 1 - 2");
+//        parse_rule(const_decl, 0, "FOO = 1.0 - 2.0");
+//        parse_rule(const_decl, 0, "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 = 5 < 3");
+//        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 = 5, BAR = FOO - 3");
+//    }
+//
+//    TEST(Should parse module level type declarations)
+//    {
+//        parse_rule(type_decl, 0, "a = Int");
+//        parse_rule(type_decl, 0, "a = Real");
+//        parse_rule(type_decl, 0, "a = Bool");
+//        parse_rule(type_decl, 0, "a = array 42 of Int");
+//        parse_rule(type_decl, 0, "a = array 42 of array 42 of Int");
+//        parse_rule(type_decl, 0, "a = record end");
+//    }
+//
+//    TEST(Should parse module level variable declarations)
+//    {
+//        parse_rule(var_decl, 0, "i : Int");
+//        parse_rule(var_decl, 0, "i : Real");
+//        parse_rule(var_decl, 0, "i : Bool");
+////        parse_rule(var_decl, 0, "x,y,z : Int");
+//    }
+//
+//    TEST(Should parse module level procedure declarations)
+//    {
+//        parse_rule(proc_decl, 0,
+//            "procedure Foo*() : Int\n"
+//            "begin\n"
+//            "    return 1;\n"
+//            "end"
+//         );
+//    }
 }
 #endif
index e0679860d29dd919aa9525074c293086e8c76c73..b862ea7b4cea3e921d8986ab16ae1ae6a268f2c4 100644 (file)
@@ -6,34 +6,34 @@ module Module
 
 const
   A = true
-  B = 42
+  B = -42
 
-type
-  TypeA = Int
-  TypeB = array 5 of Int
-  TypeC = array 5 of array 10 of Int
-  TypeD = record
-    x,y : Int
-    label : array 10 of Int
-    dim : record
-      w,h : Int
-    end
-  end
-  TypeE = record
-    i : Int
-    a : array 5 of Int
-  end
-  TypeF = array 5 of TypeE
+#type
+#  TypeA = Int
+#  TypeB = array 5 of Int
+#  TypeC = array 5 of array 10 of Int
+#  TypeD = record
+#    x,y : Int
+#    label : array 10 of Int
+#    dim : record
+#      w,h : Int
+#    end
+#  end
+#  TypeE = record
+#    i : Int
+#    a : array 5 of Int
+#  end
+#  TypeF = array 5 of TypeE
 
-var
-  a : Bool
-  b : Int
-  c : Int
-  d : Real
-  e : array 5 of array 10 of Int
-  f : TypeD
-  g : array 5 of Int
-  h : TypeF
+#var
+#  a : Bool
+#  b : Int
+#  c : Int
+#  d : Real
+#  e : array 5 of array 10 of Int
+#  f : TypeD
+#  g : array 5 of Int
+#  h : TypeF
 
 #procedure Foo*(e : Int, z : Int, q1 : TypeD, q2 : array 5 of Int) : Int
 #  const FOO = 2
@@ -53,7 +53,7 @@ var
 #    return a;
 #end
 
-begin
+#begin
 #    h[1].i = 42;
 #  a = true;
 #  a = A;
@@ -134,8 +134,6 @@ begin
 #    e[0][9] = 42;
 
 #    c = Bar(42);
-
-    c = 42;
-    c = 24;
-
-end
+#    c = 42;
+#    c = 24;
+#end