]> git.mdlowis.com Git - proto/obnc.git/commitdiff
constant folding working for new ssa form
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 21 Jul 2021 03:30:09 +0000 (23:30 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 21 Jul 2021 03:30:09 +0000 (23:30 -0400)
cerise/src/ast.c
cerise/src/grammar.c
cerise/src/ssa.c
cerise/tests/Module.m

index 403445f08b96569ec2d0068b568b28ba79446104..d8de21b666b9f9ab6acda03b095a13031dd69d83 100644 (file)
     <BLK>   <PL> <H>   <T>      Basic Block
 
 */
-#if 0
-AstNode* ast_bool(AstNode* block, bool val);
-AstNode* ast_int(AstNode* block, long long val);
-AstNode* ast_real(AstNode* block, double val);
-AstNode* ast_ident(AstNode* block, Parser* p, long long index);
-AstNode* ast_op(AstNode* block, int op, AstNode* left, AstNode* right);
-AstNode* ast_store(AstNode* block, AstNode* dest, AstNode* offset, AstNode* value);
-AstNode* ast_return(AstNode* block, AstNode* expr, AstNode* dest);
-AstNode* ast_if(AstNode* block, AstNode* cond, AstNode* dest1, AstNode* dest2);
-// while
-// foreach
-// case
-
-/* identifier references and literal values */
-typedef struct {
-    AstNodeHeader hdr;
-    union {
-        long long i;
-        double f;
-        char* s;
-    } val;
-    long long tag;
-} AstValue;
-
-typedef struct {
-    AstNodeHeader hdr;
-    AstNode* dest;
-    AstNode* left;
-    AstNode* right;
-} AstOp;
-
-typedef struct {
-    AstNodeHeader hdr;
-    AstNode* head;
-    AstNode* tail;
-} AstBlock;
-
-#else
-
-typedef struct {
-    AstNodeHeader hdr;
-    union {
-        long long i;
-        double f;
-        char* s;
-    } val;
-    long long tag;
-} AstValue;
-
-#endif
-
-bool ast_isconst(AstNode* node)
-{
-    bool ret;
-    switch (node->hdr.code)
-    {
-        case BOOL:
-        case INT:
-        case REAL:
-            ret = true;
-            break;
-
-        default:
-            ret = false;
-            break;
-    }
-    return ret;
-}
-
-bool ast_areconst(AstNode* left, AstNode* right)
-{
-    return ast_isconst(left) && ast_isconst(right);
-}
-
-static AstNode* ast_new(int code, Type* type, AstNode* l0, AstNode* l1, AstNode* l2)
-{
-    AstNode* node = calloc(1, sizeof(AstNode));
-    node->hdr.code = code;
-    node->hdr.type = type;
-    node->links[0] = l0;
-    node->links[1] = l1;
-    node->links[2] = l2;
-    return node;
-}
-
-static AstNode* ast_clone(AstNode* parent)
-{
-    AstNode* node = calloc(1, sizeof(AstNode));
-    *node = *parent;
-    return node;
-}
-
-AstNode* ast_ident(Parser* p, long long index)
-{
-    Symbol* sym = symbol_getbyid(p, (size_t)index);
-    AstNode* node;
-    if (sym && sym->class == SYM_CONST)
-    {
-        assert(sym->value != NULL);
-        node = ast_clone(sym->value);
-    }
-    else
-    {
-        node = ast_new(IDENT, sym->type, NULL, NULL, NULL);
-        ((AstValue*)node)->val.i = index;
-    }
-    return (AstNode*)node;
-}
-
-AstNode* ast_bool(Parser* p, bool val)
-{
-    (void)p;
-    AstValue* node = (AstValue*)ast_new(BOOL, &BoolType, NULL, NULL, NULL);
-    node->val.i = val;
-    return (AstNode*)node;
-}
-
-AstNode* ast_int(Parser* p, long long val)
-{
-    (void)p;
-    AstValue* node = (AstValue*)ast_new(INT, &IntType, NULL, NULL, NULL);
-    node->val.i = val;
-    return (AstNode*)node;
-}
-
-AstNode* ast_real(Parser* p, double val)
-{
-    (void)p;
-    AstValue* node = (AstValue*)ast_new(REAL, &RealType, NULL, NULL, NULL);
-    node->val.f = val;
-    return (AstNode*)node;
-}
-
-bool ast_asbool(AstNode* node)
-{
-    assert(node->hdr.type->form == FORM_BOOL);
-    return (bool)(((AstValue*)node)->val.i);
-}
-
-long long ast_asint(AstNode* node)
-{
-    assert(node->hdr.type->form == FORM_INT);
-    return ((AstValue*)node)->val.i;
-}
-
-double ast_asreal(AstNode* node)
-{
-    assert(node->hdr.type->form == FORM_REAL);
-    return ((AstValue*)node)->val.f;
-}
-
-static AstNode* ast_binop(int op, AstNode* left, AstNode* right)
-{
-    assert(left);
-    assert(right);
-    AstNode* ret = NULL;
-    if (ast_areconst(left,right))
-    {
-        AstValue* a = (AstValue*)left;
-        AstValue* b = (AstValue*)right;
-        if (a->hdr.type->form == FORM_INT || a->hdr.type->form == FORM_BOOL)
-        {
-            switch (op)
-            {
-                case '+': a->val.i = a->val.i +  b->val.i; break;
-                case '-': a->val.i = a->val.i -  b->val.i; break;
-                case '*': a->val.i = a->val.i *  b->val.i; break;
-                case '/': a->val.i = a->val.i /  b->val.i; break;
-                case '%': a->val.i = a->val.i %  b->val.i; break;
-                case AND: a->val.i = a->val.i && b->val.i; break;
-                case OR:  a->val.i = a->val.i || b->val.i; break;
-
-                case EQ:
-                    a->val.i = a->val.i == b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case NEQ:
-                    a->val.i = a->val.i != b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case '<':
-                    a->val.i = a->val.i < b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case LTEQ:
-                    a->val.i = a->val.i <= b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case '>':
-                    a->val.i = a->val.i > b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case GTEQ:
-                    a->val.i = a->val.i >= b->val.i;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                default:
-                    assert(!"not a valid op");
-                    break;
-            }
-        }
-        else if (a->hdr.type->form == FORM_REAL)
-        {
-            switch (op)
-            {
-                case '+': a->val.f = a->val.f +  b->val.f; break;
-                case '-': a->val.f = a->val.f -  b->val.f; break;
-                case '*': a->val.f = a->val.f *  b->val.f; break;
-                case '/': a->val.f = a->val.f /  b->val.f; break;
-
-                case EQ:
-                    a->val.f = a->val.f == b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case NEQ:
-                    a->val.f = a->val.f != b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case '<':
-                    a->val.f = a->val.f < b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case LTEQ:
-                    a->val.f = a->val.f <= b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case '>':
-                    a->val.f = a->val.f > b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                case GTEQ:
-                    a->val.f = a->val.f >= b->val.f;
-                    a->hdr.type = &BoolType;
-                    break;
-
-                default:
-                    assert(!"not a valid op");
-                    break;
-            }
-        }
-        else
-        {
-            assert(!"not a valid form");
-        }
-        ret = (AstNode*)a;
-    }
-    else
-    {
-        switch (op)
-        {
-            case EQ:
-            case NEQ:
-            case '<':
-            case LTEQ:
-            case '>':
-            case GTEQ:
-                ret = ast_new(op, &BoolType, left, right, NULL);
-                break;
-
-            default:
-                ret = ast_new(op, left->hdr.type, left, right, NULL);
-                break;
-        }
-    }
-    return ret;
-}
-
-static AstNode* ast_unop(int op, AstNode* operand)
-{
-    assert(operand);
-    AstNode* ret = NULL;
-    if (ast_isconst(operand))
-    {
-        AstValue* a = (AstValue*)operand;
-        if (a->hdr.type->form == FORM_INT)
-        {
-            switch (op)
-            {
-                case '+': a->val.i = +a->val.i;      break;
-                case '-': a->val.i = -a->val.i;      break;
-                default:  assert(!"not a valid op"); break;
-            }
-        }
-        else if (a->hdr.type->form == FORM_REAL)
-        {
-            switch (op)
-            {
-                case '+': a->val.f = +a->val.f;      break;
-                case '-': a->val.f = -a->val.f;      break;
-                default:  assert(!"not a valid op"); break;
-            }
-        }
-        else if (a->hdr.type->form == FORM_BOOL)
-        {
-            switch (op)
-            {
-                case NOT: a->val.i = !a->val.i;      break;
-                default:  assert(!"not a valid op"); break;
-            }
-        }
-        else
-        {
-            assert(!"not a valid form");
-        }
-        ret = (AstNode*)a;
-    }
-    else
-    {
-        ret = ast_new(op, operand->hdr.type, operand, NULL, NULL);
-    }
-    return ret;
-}
-
-AstNode* ast_op(Parser* p, int op, AstNode* left, AstNode* right)
-{
-    (void)p;
-    return (right
-        ? ast_binop(op, left, right)
-        : ast_unop(op, left));
-}
-
-AstNode* ast_store(AstNode* dest, AstNode* value)
-{
-    /* TODO: validate left-hand side is assignable */
-    return ast_new('=', &VoidType, dest, value, NULL);
-}
-
-static Field* get_field(Parser* p, Type* type, char* name)
-{
-    Field* curr = type->fields;
-    while (curr)
-    {
-        if (curr->name && !strcmp(curr->name, name))
-        {
-            break;
-        }
-        curr = curr->next;
-    }
-    if (!curr)
-    {
-        error(p, "record has no such field '%s'\n", name);
-    }
-    return curr;
-}
-
-AstNode* ast_fieldref(Parser* p, AstNode* record, char* fname)
-{
-    Field* field = get_field(p, record->hdr.type, fname);
-    AstNode* offset = ast_int(p, field->offset);
-    if (record->hdr.code == '.')
-    {
-        /* accumulate the offset into an existing record access */
-        record->links[1] = ast_binop('+', record->links[1], offset);
-        record->hdr.type = field->type;
-    }
-    else
-    {
-        /* create a new record access node */
-        record = ast_new('.', field->type, record, offset, NULL);
-    }
-    return record;
-}
-
-AstNode* ast_index(Parser* p, AstNode* array, AstNode* index)
-{
-    if (ast_isconst(index) && ast_asint(index) >= array->hdr.type->size)
-    {
-        error(p, "constant array index out of bounds");
-    }
-    return ast_new('[', array->hdr.type->base, array, index, NULL);
-}
-
-AstNode* ast_block(void)
-{
-    return ast_new(BEGIN, &VoidType, NULL, NULL, NULL);
-}
-
-static void append(AstNode* node, int offset, AstNode* first, AstNode* last)
-{
-    if (!node->links[offset + 0])
-    {
-        node->links[offset + 0] = first;
-        node->links[offset + 1] = last;
-    }
-    else
-    {
-        node->links[offset + 1]->hdr.next = first;
-        node->links[offset + 1] = last;
-    }
-}
-
-void ast_block_add(AstNode* blk, AstNode* stmt)
-{
-    assert(blk->hdr.code == BEGIN);
-    /* if we recieve a BEGIN block, we faltten it into the block by
-        appending all its statemtents */
-    if (stmt->hdr.code == BEGIN)
-    {
-        append(blk, 0, stmt->links[0], stmt->links[1]);
-    }
-    /* otherwise just append the statement to the block */
-    else
-    {
-        append(blk, 0, stmt, stmt);
-    }
-}
-
-AstNode* ast_call(AstNode* func)
-{
-    return ast_new(CALL, func->hdr.type, func, NULL, NULL);
-}
-
-void ast_call_add(AstNode* func, AstNode* arg)
-{
-    append(func, 1, arg, arg);
-}
-
-AstNode* ast_if(AstNode* cond, AstNode* br1, AstNode* br2)
-{
-    AstNode* ret;
-    if (ast_isconst(cond))
-    {
-        ret = (ast_asbool(cond) ? br1 : br2);
-    }
-    else
-    {
-        ret = ast_new(IF, &VoidType, cond, br1, br2);
-    }
-    return ret;
-}
-
-AstNode* ast_return(AstNode* expr)
-{
-    return ast_new(RETURN, &VoidType, expr, NULL, NULL);
-}
-
-static void print_indent(int indent, char* str)
-{
-    /* print the indent */
-    for (int i = 0; i < indent; i++)
-    {
-        printf("  ");
-    }
-    if (str)
-    {
-        printf("%s", str);
-    }
-}
-
-static void print_opcode(AstNode* node)
-{
-    int op = node->hdr.code;
-    if (op < 256)
-    {
-        printf("(%c\n", op);
-    }
-    else if (op == RETURN)
-    {
-        printf("(return\n");
-    }
-    else if (op == IF)
-    {
-        printf("(if\n");
-    }
-    else
-    {
-        printf("(%d\n", op);
-    }
-}
-
-static void print(Parser* p, AstNode* node, int indent)
-{
-    assert(node);
-    print_indent(indent, NULL);
-
-    /* now print the data */
-    switch(node->hdr.code)
-    {
-        case BOOL:
-            printf("B:%lld", ((AstValue*)node)->val.i);
-            break;
-
-        case INT:
-            printf("I:%lld", ((AstValue*)node)->val.i);
-            break;
-
-        case REAL:
-            printf("R:%f", ((AstValue*)node)->val.f);
-            break;
-
-        case IDENT:
-            {
-                Symbol* s = symbol_getbyid(p, ((AstValue*)node)->val.i);
-                printf("%s.%lld", s->name, ((AstValue*)node)->tag);
-            }
-            break;
-
-        case '.':
-            printf("(field-ref\n");
-            print(p, node->links[0], indent+1);
-            print(p, node->links[1], indent+1);
-            print_indent(indent, ")");
-            break;
-
-        case '[':
-            printf("(array-index\n");
-            print(p, node->links[0], indent+1);
-            print(p, node->links[1], indent+1);
-            print_indent(indent, ")");
-            break;
-
-        case BEGIN:
-            printf("(begin\n");
-            for (AstNode* curr = node->links[0]; curr; curr = curr->hdr.next)
-            {
-                print(p, curr, indent+1);
-            }
-            print_indent(indent, ")");
-            break;
-
-        case CALL:
-            printf("(call\n");
-            print(p, node->links[0], indent+1);
-            for (AstNode* curr = node->links[1]; curr; curr = curr->hdr.next)
-            {
-                print(p, curr, indent+1);
-            }
-            print_indent(indent, ")");
-            break;
-
-        case IF:
-            printf("(if\n");
-            print(p, node->links[0], indent+1);
-            print(p, node->links[1], indent+1);
-            if (node->links[2])
-            {
-                print(p, node->links[2], indent+1);
-            }
-            print_indent(indent, ")");
-            break;
-
-        default:
-            if (node->links[1])
-            {
-                print_opcode(node);
-                print(p, node->links[0], indent+1);
-                print(p, node->links[1], indent+1);
-                print_indent(indent, ")");
-            }
-            else
-            {
-                print_opcode(node);
-                print(p, node->links[0], indent+1);
-                print_indent(indent, ")");
-            }
-            break;
-    }
-    puts("");
-}
-
-void ast_print(Parser* p, AstNode* node)
-{
-    print(p, node, 0);
-}
+//#if 0
+//AstNode* ast_bool(AstNode* block, bool val);
+//AstNode* ast_int(AstNode* block, long long val);
+//AstNode* ast_real(AstNode* block, double val);
+//AstNode* ast_ident(AstNode* block, Parser* p, long long index);
+//AstNode* ast_op(AstNode* block, int op, AstNode* left, AstNode* right);
+//AstNode* ast_store(AstNode* block, AstNode* dest, AstNode* offset, AstNode* value);
+//AstNode* ast_return(AstNode* block, AstNode* expr, AstNode* dest);
+//AstNode* ast_if(AstNode* block, AstNode* cond, AstNode* dest1, AstNode* dest2);
+//// while
+//// foreach
+//// case
+
+///* identifier references and literal values */
+//typedef struct {
+//    AstNodeHeader hdr;
+//    union {
+//        long long i;
+//        double f;
+//        char* s;
+//    } val;
+//    long long tag;
+//} AstValue;
+//
+//typedef struct {
+//    AstNodeHeader hdr;
+//    AstNode* dest;
+//    AstNode* left;
+//    AstNode* right;
+//} AstOp;
+//
+//typedef struct {
+//    AstNodeHeader hdr;
+//    AstNode* head;
+//    AstNode* tail;
+//} AstBlock;
+//
+//#else
+//
+//typedef struct {
+//    AstNodeHeader hdr;
+//    union {
+//        long long i;
+//        double f;
+//        char* s;
+//    } val;
+//    long long tag;
+//} AstValue;
+//
+//#endif
+//
+//bool ast_isconst(AstNode* node)
+//{
+//    bool ret;
+//    switch (node->hdr.code)
+//    {
+//        case BOOL:
+//        case INT:
+//        case REAL:
+//            ret = true;
+//            break;
+//
+//        default:
+//            ret = false;
+//            break;
+//    }
+//    return ret;
+//}
+//
+//bool ast_areconst(AstNode* left, AstNode* right)
+//{
+//    return ast_isconst(left) && ast_isconst(right);
+//}
+//
+//static AstNode* ast_new(int code, Type* type, AstNode* l0, AstNode* l1, AstNode* l2)
+//{
+//    AstNode* node = calloc(1, sizeof(AstNode));
+//    node->hdr.code = code;
+//    node->hdr.type = type;
+//    node->links[0] = l0;
+//    node->links[1] = l1;
+//    node->links[2] = l2;
+//    return node;
+//}
+//
+//static AstNode* ast_clone(AstNode* parent)
+//{
+//    AstNode* node = calloc(1, sizeof(AstNode));
+//    *node = *parent;
+//    return node;
+//}
+//
+//AstNode* ast_ident(Parser* p, long long index)
+//{
+//    Symbol* sym = symbol_getbyid(p, (size_t)index);
+//    AstNode* node;
+//    if (sym && sym->class == SYM_CONST)
+//    {
+//        assert(sym->value != NULL);
+//        node = ast_clone(sym->value);
+//    }
+//    else
+//    {
+//        node = ast_new(IDENT, sym->type, NULL, NULL, NULL);
+//        ((AstValue*)node)->val.i = index;
+//    }
+//    return (AstNode*)node;
+//}
+//
+//AstNode* ast_bool(Parser* p, bool val)
+//{
+//    (void)p;
+//    AstValue* node = (AstValue*)ast_new(BOOL, &BoolType, NULL, NULL, NULL);
+//    node->val.i = val;
+//    return (AstNode*)node;
+//}
+//
+//AstNode* ast_int(Parser* p, long long val)
+//{
+//    (void)p;
+//    AstValue* node = (AstValue*)ast_new(INT, &IntType, NULL, NULL, NULL);
+//    node->val.i = val;
+//    return (AstNode*)node;
+//}
+//
+//AstNode* ast_real(Parser* p, double val)
+//{
+//    (void)p;
+//    AstValue* node = (AstValue*)ast_new(REAL, &RealType, NULL, NULL, NULL);
+//    node->val.f = val;
+//    return (AstNode*)node;
+//}
+//
+//bool ast_asbool(AstNode* node)
+//{
+//    assert(node->hdr.type->form == FORM_BOOL);
+//    return (bool)(((AstValue*)node)->val.i);
+//}
+//
+//long long ast_asint(AstNode* node)
+//{
+//    assert(node->hdr.type->form == FORM_INT);
+//    return ((AstValue*)node)->val.i;
+//}
+//
+//double ast_asreal(AstNode* node)
+//{
+//    assert(node->hdr.type->form == FORM_REAL);
+//    return ((AstValue*)node)->val.f;
+//}
+//
+//static AstNode* ast_binop(int op, AstNode* left, AstNode* right)
+//{
+//    assert(left);
+//    assert(right);
+//    AstNode* ret = NULL;
+//    if (ast_areconst(left,right))
+//    {
+//        AstValue* a = (AstValue*)left;
+//        AstValue* b = (AstValue*)right;
+//        if (a->hdr.type->form == FORM_INT || a->hdr.type->form == FORM_BOOL)
+//        {
+//            switch (op)
+//            {
+//                case '+': a->val.i = a->val.i +  b->val.i; break;
+//                case '-': a->val.i = a->val.i -  b->val.i; break;
+//                case '*': a->val.i = a->val.i *  b->val.i; break;
+//                case '/': a->val.i = a->val.i /  b->val.i; break;
+//                case '%': a->val.i = a->val.i %  b->val.i; break;
+//                case AND: a->val.i = a->val.i && b->val.i; break;
+//                case OR:  a->val.i = a->val.i || b->val.i; break;
+//
+//                case EQ:
+//                    a->val.i = a->val.i == b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case NEQ:
+//                    a->val.i = a->val.i != b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case '<':
+//                    a->val.i = a->val.i < b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case LTEQ:
+//                    a->val.i = a->val.i <= b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case '>':
+//                    a->val.i = a->val.i > b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case GTEQ:
+//                    a->val.i = a->val.i >= b->val.i;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                default:
+//                    assert(!"not a valid op");
+//                    break;
+//            }
+//        }
+//        else if (a->hdr.type->form == FORM_REAL)
+//        {
+//            switch (op)
+//            {
+//                case '+': a->val.f = a->val.f +  b->val.f; break;
+//                case '-': a->val.f = a->val.f -  b->val.f; break;
+//                case '*': a->val.f = a->val.f *  b->val.f; break;
+//                case '/': a->val.f = a->val.f /  b->val.f; break;
+//
+//                case EQ:
+//                    a->val.f = a->val.f == b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case NEQ:
+//                    a->val.f = a->val.f != b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case '<':
+//                    a->val.f = a->val.f < b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case LTEQ:
+//                    a->val.f = a->val.f <= b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case '>':
+//                    a->val.f = a->val.f > b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                case GTEQ:
+//                    a->val.f = a->val.f >= b->val.f;
+//                    a->hdr.type = &BoolType;
+//                    break;
+//
+//                default:
+//                    assert(!"not a valid op");
+//                    break;
+//            }
+//        }
+//        else
+//        {
+//            assert(!"not a valid form");
+//        }
+//        ret = (AstNode*)a;
+//    }
+//    else
+//    {
+//        switch (op)
+//        {
+//            case EQ:
+//            case NEQ:
+//            case '<':
+//            case LTEQ:
+//            case '>':
+//            case GTEQ:
+//                ret = ast_new(op, &BoolType, left, right, NULL);
+//                break;
+//
+//            default:
+//                ret = ast_new(op, left->hdr.type, left, right, NULL);
+//                break;
+//        }
+//    }
+//    return ret;
+//}
+//
+//static AstNode* ast_unop(int op, AstNode* operand)
+//{
+//    assert(operand);
+//    AstNode* ret = NULL;
+//    if (ast_isconst(operand))
+//    {
+//        AstValue* a = (AstValue*)operand;
+//        if (a->hdr.type->form == FORM_INT)
+//        {
+//            switch (op)
+//            {
+//                case '+': a->val.i = +a->val.i;      break;
+//                case '-': a->val.i = -a->val.i;      break;
+//                default:  assert(!"not a valid op"); break;
+//            }
+//        }
+//        else if (a->hdr.type->form == FORM_REAL)
+//        {
+//            switch (op)
+//            {
+//                case '+': a->val.f = +a->val.f;      break;
+//                case '-': a->val.f = -a->val.f;      break;
+//                default:  assert(!"not a valid op"); break;
+//            }
+//        }
+//        else if (a->hdr.type->form == FORM_BOOL)
+//        {
+//            switch (op)
+//            {
+//                case NOT: a->val.i = !a->val.i;      break;
+//                default:  assert(!"not a valid op"); break;
+//            }
+//        }
+//        else
+//        {
+//            assert(!"not a valid form");
+//        }
+//        ret = (AstNode*)a;
+//    }
+//    else
+//    {
+//        ret = ast_new(op, operand->hdr.type, operand, NULL, NULL);
+//    }
+//    return ret;
+//}
+//
+//AstNode* ast_op(Parser* p, int op, AstNode* left, AstNode* right)
+//{
+//    (void)p;
+//    return (right
+//        ? ast_binop(op, left, right)
+//        : ast_unop(op, left));
+//}
+//
+//AstNode* ast_store(AstNode* dest, AstNode* value)
+//{
+//    /* TODO: validate left-hand side is assignable */
+//    return ast_new('=', &VoidType, dest, value, NULL);
+//}
+//
+//static Field* get_field(Parser* p, Type* type, char* name)
+//{
+//    Field* curr = type->fields;
+//    while (curr)
+//    {
+//        if (curr->name && !strcmp(curr->name, name))
+//        {
+//            break;
+//        }
+//        curr = curr->next;
+//    }
+//    if (!curr)
+//    {
+//        error(p, "record has no such field '%s'\n", name);
+//    }
+//    return curr;
+//}
+//
+//AstNode* ast_fieldref(Parser* p, AstNode* record, char* fname)
+//{
+//    Field* field = get_field(p, record->hdr.type, fname);
+//    AstNode* offset = ast_int(p, field->offset);
+//    if (record->hdr.code == '.')
+//    {
+//        /* accumulate the offset into an existing record access */
+//        record->links[1] = ast_binop('+', record->links[1], offset);
+//        record->hdr.type = field->type;
+//    }
+//    else
+//    {
+//        /* create a new record access node */
+//        record = ast_new('.', field->type, record, offset, NULL);
+//    }
+//    return record;
+//}
+//
+//AstNode* ast_index(Parser* p, AstNode* array, AstNode* index)
+//{
+//    if (ast_isconst(index) && ast_asint(index) >= array->hdr.type->size)
+//    {
+//        error(p, "constant array index out of bounds");
+//    }
+//    return ast_new('[', array->hdr.type->base, array, index, NULL);
+//}
+//
+//AstNode* ast_block(void)
+//{
+//    return ast_new(BEGIN, &VoidType, NULL, NULL, NULL);
+//}
+//
+//static void append(AstNode* node, int offset, AstNode* first, AstNode* last)
+//{
+//    if (!node->links[offset + 0])
+//    {
+//        node->links[offset + 0] = first;
+//        node->links[offset + 1] = last;
+//    }
+//    else
+//    {
+//        node->links[offset + 1]->hdr.next = first;
+//        node->links[offset + 1] = last;
+//    }
+//}
+//
+//void ast_block_add(AstNode* blk, AstNode* stmt)
+//{
+//    assert(blk->hdr.code == BEGIN);
+//    /* if we recieve a BEGIN block, we faltten it into the block by
+//        appending all its statemtents */
+//    if (stmt->hdr.code == BEGIN)
+//    {
+//        append(blk, 0, stmt->links[0], stmt->links[1]);
+//    }
+//    /* otherwise just append the statement to the block */
+//    else
+//    {
+//        append(blk, 0, stmt, stmt);
+//    }
+//}
+//
+//AstNode* ast_call(AstNode* func)
+//{
+//    return ast_new(CALL, func->hdr.type, func, NULL, NULL);
+//}
+//
+//void ast_call_add(AstNode* func, AstNode* arg)
+//{
+//    append(func, 1, arg, arg);
+//}
+//
+//AstNode* ast_if(AstNode* cond, AstNode* br1, AstNode* br2)
+//{
+//    AstNode* ret;
+//    if (ast_isconst(cond))
+//    {
+//        ret = (ast_asbool(cond) ? br1 : br2);
+//    }
+//    else
+//    {
+//        ret = ast_new(IF, &VoidType, cond, br1, br2);
+//    }
+//    return ret;
+//}
+//
+//AstNode* ast_return(AstNode* expr)
+//{
+//    return ast_new(RETURN, &VoidType, expr, NULL, NULL);
+//}
+//
+//static void print_indent(int indent, char* str)
+//{
+//    /* print the indent */
+//    for (int i = 0; i < indent; i++)
+//    {
+//        printf("  ");
+//    }
+//    if (str)
+//    {
+//        printf("%s", str);
+//    }
+//}
+//
+//static void print_opcode(AstNode* node)
+//{
+//    int op = node->hdr.code;
+//    if (op < 256)
+//    {
+//        printf("(%c\n", op);
+//    }
+//    else if (op == RETURN)
+//    {
+//        printf("(return\n");
+//    }
+//    else if (op == IF)
+//    {
+//        printf("(if\n");
+//    }
+//    else
+//    {
+//        printf("(%d\n", op);
+//    }
+//}
+//
+//static void print(Parser* p, AstNode* node, int indent)
+//{
+//    assert(node);
+//    print_indent(indent, NULL);
+//
+//    /* now print the data */
+//    switch(node->hdr.code)
+//    {
+//        case BOOL:
+//            printf("B:%lld", ((AstValue*)node)->val.i);
+//            break;
+//
+//        case INT:
+//            printf("I:%lld", ((AstValue*)node)->val.i);
+//            break;
+//
+//        case REAL:
+//            printf("R:%f", ((AstValue*)node)->val.f);
+//            break;
+//
+//        case IDENT:
+//            {
+//                Symbol* s = symbol_getbyid(p, ((AstValue*)node)->val.i);
+//                printf("%s.%lld", s->name, ((AstValue*)node)->tag);
+//            }
+//            break;
+//
+//        case '.':
+//            printf("(field-ref\n");
+//            print(p, node->links[0], indent+1);
+//            print(p, node->links[1], indent+1);
+//            print_indent(indent, ")");
+//            break;
+//
+//        case '[':
+//            printf("(array-index\n");
+//            print(p, node->links[0], indent+1);
+//            print(p, node->links[1], indent+1);
+//            print_indent(indent, ")");
+//            break;
+//
+//        case BEGIN:
+//            printf("(begin\n");
+//            for (AstNode* curr = node->links[0]; curr; curr = curr->hdr.next)
+//            {
+//                print(p, curr, indent+1);
+//            }
+//            print_indent(indent, ")");
+//            break;
+//
+//        case CALL:
+//            printf("(call\n");
+//            print(p, node->links[0], indent+1);
+//            for (AstNode* curr = node->links[1]; curr; curr = curr->hdr.next)
+//            {
+//                print(p, curr, indent+1);
+//            }
+//            print_indent(indent, ")");
+//            break;
+//
+//        case IF:
+//            printf("(if\n");
+//            print(p, node->links[0], indent+1);
+//            print(p, node->links[1], indent+1);
+//            if (node->links[2])
+//            {
+//                print(p, node->links[2], indent+1);
+//            }
+//            print_indent(indent, ")");
+//            break;
+//
+//        default:
+//            if (node->links[1])
+//            {
+//                print_opcode(node);
+//                print(p, node->links[0], indent+1);
+//                print(p, node->links[1], indent+1);
+//                print_indent(indent, ")");
+//            }
+//            else
+//            {
+//                print_opcode(node);
+//                print(p, node->links[0], indent+1);
+//                print_indent(indent, ")");
+//            }
+//            break;
+//    }
+//    puts("");
+//}
+//
+//void ast_print(Parser* p, AstNode* node)
+//{
+//    print(p, node, 0);
+//}
index 29cdc2112e4be6d055715cf4103923c7671be193..b737629a337ba6065a805473566f67a976c457ea 100644 (file)
@@ -483,7 +483,7 @@ static void const_decl(Parser* p)
         expect(p, '=');
         sym->value = expression(p);
         sym->type = sym->value->type;
-        printf("%p\n", sym->value);
+        ssa_print(p, sym->value);
     }
     while (matches(p, IDENT));
 
index 0884cd331d021710c9b0eb24a1b78c1bf611d9b0..9e3bbfdc4f55b58c94d1316a47439a47d06682c2 100644 (file)
@@ -3,8 +3,8 @@
 static SsaNode* ssa_node(int code, int mode);
 static SsaNode* binop(Parser* p, int op, SsaNode* left, SsaNode* right);
 static SsaNode* unop(Parser* p, int op, SsaNode* operand);
-static SsaNode* const_binop(Parser* p, int op, SsaNode* left, SsaNode* right);
-static SsaNode* const_unop(Parser* p, int op, SsaNode* operand);
+static SsaNode* const_binop(int op, SsaNode* left, SsaNode* right);
+static SsaNode* const_unop(int op, SsaNode* operand);
 static SsaNode* load(Parser* p, SsaNode* node);
 
 bool ssa_asbool(SsaNode* node)
@@ -16,13 +16,13 @@ bool ssa_asbool(SsaNode* node)
 long long ssa_asint(SsaNode* node)
 {
     assert(node->code == INT);
-    return (bool)(node->left.val.i);
+    return (node->left.val.i);
 }
 
 double ssa_asreal(SsaNode* node)
 {
     assert(node->code == REAL);
-    return (bool)(node->left.val.f);
+    return (node->left.val.f);
 }
 
 static SsaNode* ssa_node(int code, int mode)
@@ -37,10 +37,20 @@ static SsaNode* ssa_node(int code, int mode)
 
 SsaNode* ssa_ident(Parser* p, long long index)
 {
+    SsaNode* node;
     Symbol* sym = symbol_getbyid(p, index);
-    SsaNode* node = ssa_node(IDENT, MODE_VAR);
-    node->left.var.symid = index;
-    node->left.var.symver = sym->version;
+    if (sym->class == SYM_CONST)
+    {
+        assert(sym->value != NULL);
+        node = calloc(1, sizeof(SsaNode));
+        *node = *(sym->value);
+    }
+    else
+    {
+        node = ssa_node(IDENT, MODE_VAR);
+        node->left.var.symid = index;
+        node->left.var.symver = sym->version;
+    }
     return node;
 }
 
@@ -88,6 +98,7 @@ SsaNode* ssa_store(Parser* p, SsaNode* dest, SsaNode* value)
 
 SsaNode* ssa_fieldref(Parser* p, SsaNode* record, char* fname)
 {
+    (void)p, (void)record, (void)fname;
     assert("!record field references unimplemented");
     return NULL;
 }
@@ -150,7 +161,7 @@ static SsaNode* binop(Parser* p, int op, SsaNode* left, SsaNode* right)
     SsaNode* node = NULL;
     if (left->mode == MODE_CONST && right->mode == MODE_CONST)
     {
-        node = const_binop(p, op, left, right);
+        node = const_binop(op, left, right);
     }
     else
     {
@@ -169,7 +180,7 @@ static SsaNode* unop(Parser* p, int op, SsaNode* operand)
     SsaNode* node = NULL;
     if (operand->mode == MODE_CONST)
     {
-        node = const_unop(p, op, operand);
+        node = const_unop(op, operand);
     }
     else
     {
@@ -181,18 +192,140 @@ static SsaNode* unop(Parser* p, int op, SsaNode* operand)
     return node;
 }
 
-static SsaNode* const_binop(Parser* p, int op, SsaNode* left, SsaNode* right)
+static SsaNode* const_binop(int op, SsaNode* a, SsaNode* b)
 {
-    (void)p, (void)op, (void)left, (void)right;
-    /* perform the operation based on type and operator */
-    return NULL;
+    if (a->type->form == FORM_INT || a->type->form == FORM_BOOL)
+    {
+        switch (op)
+        {
+            case '+': a->left.val.i = a->left.val.i +  b->left.val.i; break;
+            case '-': a->left.val.i = a->left.val.i -  b->left.val.i; break;
+            case '*': a->left.val.i = a->left.val.i *  b->left.val.i; break;
+            case '/': a->left.val.i = a->left.val.i /  b->left.val.i; break;
+            case '%': a->left.val.i = a->left.val.i %  b->left.val.i; break;
+            case AND: a->left.val.i = a->left.val.i && b->left.val.i; break;
+            case OR:  a->left.val.i = a->left.val.i || b->left.val.i; break;
+
+            case EQ:
+                a->left.val.i = a->left.val.i == b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            case NEQ:
+                a->left.val.i = a->left.val.i != b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->left.val.i = a->left.val.i < b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->left.val.i = a->left.val.i <= b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->left.val.i = a->left.val.i > b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->left.val.i = a->left.val.i >= b->left.val.i;
+                a->type = &BoolType;
+                break;
+
+            default:
+                assert(!"not a left.valid op");
+                break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
+    {
+        switch (op)
+        {
+            case '+': a->left.val.f = a->left.val.f +  b->left.val.f; break;
+            case '-': a->left.val.f = a->left.val.f -  b->left.val.f; break;
+            case '*': a->left.val.f = a->left.val.f *  b->left.val.f; break;
+            case '/': a->left.val.f = a->left.val.f /  b->left.val.f; break;
+
+            case EQ:
+                a->left.val.f = a->left.val.f == b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            case NEQ:
+                a->left.val.f = a->left.val.f != b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            case '<':
+                a->left.val.f = a->left.val.f < b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            case LTEQ:
+                a->left.val.f = a->left.val.f <= b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            case '>':
+                a->left.val.f = a->left.val.f > b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            case GTEQ:
+                a->left.val.f = a->left.val.f >= b->left.val.f;
+                a->type = &BoolType;
+                break;
+
+            default:
+                assert(!"not a left.valid op");
+                break;
+        }
+    }
+    else
+    {
+        assert(!"not a left.valid form");
+    }
+    return a;
 }
 
-static SsaNode* const_unop(Parser* p, int op, SsaNode* operand)
+static SsaNode* const_unop(int op, SsaNode* a)
 {
-    (void)p, (void)op, (void)operand;
-    /* perform the operation based on type and operator */
-    return NULL;
+    if (a->type->form == FORM_INT)
+    {
+        switch (op)
+        {
+            case '+': a->left.val.i = +a->left.val.i; break;
+            case '-': a->left.val.i = -a->left.val.i; break;
+            default:  assert(!"not a valid op");      break;
+        }
+    }
+    else if (a->type->form == FORM_REAL)
+    {
+        switch (op)
+        {
+            case '+': a->left.val.f = +a->left.val.f; break;
+            case '-': a->left.val.f = -a->left.val.f; break;
+            default:  assert(!"not a valid op");      break;
+        }
+    }
+    else if (a->type->form == FORM_BOOL)
+    {
+        switch (op)
+        {
+            case NOT: a->left.val.i = !a->left.val.i; break;
+            default:  assert(!"not a valid op");      break;
+        }
+    }
+    else
+    {
+        assert(!"not a valid form");
+    }
+
+    return a;
 }
 
 static SsaNode* load(Parser* p, SsaNode* node)
@@ -350,11 +483,26 @@ static SsaNode* load(Parser* p, SsaNode* node)
 //{
 //    print(p, node, 0);
 //}
-//
+
 void ssa_print(Parser* p, SsaNode* expr)
 {
-//    switch (expr->code)
-//    {
-//        case
-//    }
+    (void)p;
+    switch(expr->code)
+    {
+        case BOOL:
+            printf("(Bool)%d\n", ssa_asbool(expr));
+            break;
+
+        case INT:
+            printf("(Int)%lld\n", ssa_asint(expr));
+            break;
+
+        case REAL:
+            printf("(Real)%f\n", ssa_asreal(expr));
+            break;
+
+        default:
+            printf("???\n");
+            break;
+    }
 }
index 995f67b18513991d955639db8c5cdb499fa3c7d2..d6e2e4f63630d60c044ff6ae4a8f1aac3937c19f 100644 (file)
@@ -9,10 +9,10 @@ const
   B* = 42
   C* = 42.0
   D = -B
-#  E = -C
-#  F = not A
-#  G = B + 2 - 2 * 2
-#  H = false or A
+  E = -C
+  F = not A
+  G = B + 2 - 2 * 2
+  H = false or A
 
 #type
 #  TypeA* = Int