<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);
+//}
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)
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)
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;
}
SsaNode* ssa_fieldref(Parser* p, SsaNode* record, char* fname)
{
+ (void)p, (void)record, (void)fname;
assert("!record field references unimplemented");
return NULL;
}
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
{
SsaNode* node = NULL;
if (operand->mode == MODE_CONST)
{
- node = const_unop(p, op, operand);
+ node = const_unop(op, operand);
}
else
{
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)
//{
// 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;
+ }
}