From 4ce32af784d3f93f8865dc2ba8f1f97f4d247cb5 Mon Sep 17 00:00:00 2001 From: Anicka Bernathova Date: Tue, 14 Jul 2009 23:36:34 +0200 Subject: [PATCH] start with conditions --- code.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++------ lists.c | 13 ++++++ lists.h | 1 + umpf.h | 12 ++++-- 4 files changed, 132 insertions(+), 16 deletions(-) diff --git a/code.c b/code.c index af23489..de0ed89 100644 --- a/code.c +++ b/code.c @@ -70,18 +70,21 @@ store_const(char* c) } static void -new_instr(struct code c) +new_instr(struct code c, struct list* where) { struct code* p = xmalloc(sizeof(struct code)); *p = c; - list_add_last(&input_code, &p->car); + if (where) + list_add_last(where, &p->car); + else + list_add_last(&input_code, &p->car); } /* return number of variable where lies result * pref_var < 0 => no preference */ static int -evaluate(struct tree* t, int pref_var) +evaluate(struct tree* t, int pref_var, struct list* where) { struct code ins; @@ -89,8 +92,8 @@ evaluate(struct tree* t, int pref_var) return t->pt.leaf.n; } else if (t->st == ST_OP) { int left, right; - left = evaluate(t->pt.op.left, -1); - right = evaluate(t->pt.op.right, -1); + left = evaluate(t->pt.op.left, -1, where); + right = evaluate(t->pt.op.right, -1, where); switch (t->pt.op.op) { case '.': ins.opcode = CAT; @@ -100,7 +103,7 @@ evaluate(struct tree* t, int pref_var) ins.u.cat.res = pref_var; else ins.u.cat.res = current_varcode++;; - new_instr(ins); + new_instr(ins, where); return ins.u.cat.res; break; default: @@ -112,20 +115,92 @@ evaluate(struct tree* t, int pref_var) } static void -do_ass(struct tree* t) +do_ass(struct tree* t, struct list* where) { int var_l, var_r; struct code ins; var_l = t->pt.ass.left->pt.leaf.n; - var_r = evaluate(t->pt.ass.right, -1); + var_r = evaluate(t->pt.ass.right, -1, where); ins.opcode = SET; ins.u.set.l = var_l; ins.u.set.r = var_r; - new_instr(ins); + new_instr(ins, where); } +static int +eval_cond(struct tree *t, int pref_var, struct list* where) +{ + struct code ins; + int left, right; + if (t->pt.cond.type == JUST_BOOL) { + if (t->pt.cond.left->st == ST_LEAF) + return t->pt.cond.left->pt.leaf.n; + if (t->pt.cond.left->st == ST_OP) + return evaluate(t->pt.cond.left, -1, where); + else + die("eval_cond: %d cannot be JUST_BOOL\n", + t->pt.cond.left->st); + } + if (t->pt.cond.type == OP_REL) { + left = evaluate(t->pt.cond.left, -1, where); + right = evaluate(t->pt.cond.right, -1, where); + + switch (t->pt.cond.op) { + case '>': + ins.opcode = GT; + ins.u.gt.l = left; + ins.u.gt.r = right; + if (pref_var >= 0) + ins.u.gt.res = pref_var; + else + ins.u.gt.res = current_varcode++;; + new_instr(ins, where); + return ins.u.gt.res; + break; + /* fixme: do more of them */ + default: + die("eval_cond: unknown relation op %c\n", + t->pt.cond.op); + + } + } +} + +static void +do_if(struct tree *t, struct list* where) +{ + int c; + struct code ins, nop, jmp; + struct list* if_branch = xmalloc(sizeof(struct list)); + struct list* else_branch = xmalloc(sizeof(struct list)); + + list_init(if_branch); + list_init(else_branch); + nop.opcode = NOP; + jmp.opcode = JUMP; + + c = eval_cond(t->pt.tif.c, -1, where); + + compile(t->pt.tif.i, if_branch); + compile(t->pt.tif.i, else_branch); + new_instr(nop, if_branch); + new_instr(nop, else_branch); + jmp.u.jump.target = list_last(else_branch); + new_instr(jmp, if_branch); + + ins.opcode = JUMP_UNLESS; + ins.u.jump_unless.cond = c; + ins.u.jump_unless.target = list_last(if_branch); + new_instr(ins, where); + list_cat(where, if_branch); + list_cat(where, else_branch); + + free(if_branch); + free(else_branch); +} + static void reset_temp_var_count(void) { @@ -133,23 +208,32 @@ reset_temp_var_count(void) } void -compile(struct tree* t) +compile(struct tree* t, struct list* where) { if (!t) return; + if (! where) + where = &input_code; + switch(t->st) { case ST_BLOCK: reset_temp_var_count(); - compile(t->pt.block.head); - compile(t->pt.block.tail); + compile(t->pt.block.head, where); + compile(t->pt.block.tail, where); break; case ST_EMPTY: break; case ST_ASS: - do_ass(t); + do_ass(t, where); break; case ST_OP: + evaluate(t, -1, where); //emit warning? break; + case ST_IF: + do_if(t, where); + break; + case ST_COND: + eval_cond(t, -1, where); // warn? default: die("compile: got to default"); } @@ -169,6 +253,18 @@ print_code(void) printf("CAT %d %d %d\n", p->u.cat.l, p->u.cat.r, p->u.cat.res); break; + case JUMP: + printf("JUMP %d\n", (int) p->u.jump.target); + break; + case JUMP_UNLESS: + printf("JUMP_UNLESS %d %d\n", p->u.jump_unless.cond,(int) p->u.jump_unless.target); + break; + case GT: + printf("GT %d %d %d\n", p->u.gt.l, p->u.gt.r, p->u.gt.res); + break; + case NOP: + puts("NOP"); + break; default: printf("not implemented, opcode: %d\n", p->opcode); diff --git a/lists.c b/lists.c index ae9c3d7..9d64e28 100644 --- a/lists.c +++ b/lists.c @@ -111,3 +111,16 @@ list_del_last(struct list* l) return del; } + +void +list_cat(struct list* dst, struct list* src) +{ + struct node* dst_last = dst->head.prev; + struct node* src_first = src->head.next; + struct node* src_last = src->head.prev; + + dst_last->next = src_first; + src_first->prev = dst_last; + src_last->next = &dst->head; + dst->head.prev = src_last; +} diff --git a/lists.h b/lists.h index e430f02..e4e30bd 100644 --- a/lists.h +++ b/lists.h @@ -21,3 +21,4 @@ void list_add_before(struct node* orig, struct node* new); void list_del_node(struct node* n); void* list_del_first(struct list* l); void* list_del_last(struct list* l); +void list_cat(struct list* dst, struct list* src); diff --git a/umpf.h b/umpf.h index 179229f..b5b7df8 100644 --- a/umpf.h +++ b/umpf.h @@ -26,7 +26,7 @@ struct tree { enum { OP_REL, OP_BOOL, - JUST_BOOL /* value only in left */ + JUST_BOOL /* value only in left, no op */ } type; int op; struct tree* left; @@ -127,7 +127,8 @@ struct code { DELIVER, CALL_EXT, NOP, - CAT + CAT, + GT } opcode; union { @@ -153,6 +154,11 @@ struct code { } cat; struct { } nop; + struct { + int l; + int r; + int res; /* result */ + } gt; } u; }; @@ -172,7 +178,7 @@ int cur_const_n; int cur_const_s; void init(void); -void compile(struct tree* t); +void compile(struct tree* t, struct list* where); int find_var(char* name, struct list* hash); int store_const(char* c); struct list* new_var_hash(void); -- 2.39.2