X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=code.c;h=59742fc9a8292c7241ca4241dafacacbdde840b6;hb=43367dfb74d85a732b8973140a7b87a888b11902;hp=7c2296829c80268d092fb0cdc0dcfa47fa008c41;hpb=80e68c40229bccd38ec4d89737c4cae6ecb41e7c;p=umpf.git diff --git a/code.c b/code.c index 7c22968..59742fc 100644 --- a/code.c +++ b/code.c @@ -5,9 +5,6 @@ #include "umpf.h" -#define HASHSIZE 103 -#define MAGIC 19 - struct list* new_var_hash(void) { @@ -21,7 +18,7 @@ new_var_hash(void) return res; } -static int +int get_bucket_number(char* name) { unsigned int n = 0; @@ -35,7 +32,6 @@ get_bucket_number(char* name) return n; } -/* if not found, variable with value "" is created */ int find_var(char* name, struct list* hash) { @@ -80,38 +76,58 @@ new_instr(struct code c, struct list* where) list_add_last(&input_code, &p->car); } +static int +new_3par_instr(int opcode, int left, int right, int pref_var, + struct list* where) +{ + struct code ins; + + ins.opcode = opcode; + ins.u.tpop.l = left; + ins.u.tpop.r = right; + if (pref_var >= 0) + ins.u.tpop.res = pref_var; + else + ins.u.tpop.res = current_varcode++;; + new_instr(ins, where); + return ins.u.tpop.res; +} + /* return number of variable where lies result * pref_var < 0 => no preference */ static int evaluate(struct tree* t, int pref_var, struct list* where) { - struct code ins; - if (t->st == ST_LEAF) { return t->pt.leaf.n; - } else if (t->st == ST_OP) { - int left, right; - 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; - ins.u.tpop.l = left; - ins.u.tpop.r = right; - if (pref_var >= 0) - ins.u.tpop.res = pref_var; - else - ins.u.tpop.res = current_varcode++;; - new_instr(ins, where); - return ins.u.tpop.res; - break; - default: - die("evaluate: got to default"); - } - } else - die("evaluate: I can evaluate only expressions but I got %d", - t->st); + } + int left, right; + left = evaluate(t->pt.op.left, -1, where); + right = evaluate(t->pt.op.right, -1, where); + switch (t->pt.op.op) { + case '.': + return new_3par_instr(OPC_CAT, left, + right, pref_var, where); + break; + case '+': + return new_3par_instr(OPC_PLUS, left, + right, pref_var, where); + break; + case '-': + return new_3par_instr(OPC_MINUS, left, + right, pref_var, where); + break; + case '*': + return new_3par_instr(OPC_MUL, left, + right, pref_var, where); + break; + case '/': + return new_3par_instr(OPC_DIV, left, + right, pref_var, where); + break; + } + die("evaluate: Never can get here :)"); } static void @@ -122,30 +138,13 @@ do_ass(struct tree* t, struct list* where) var_l = t->pt.ass.left->pt.leaf.n; var_r = evaluate(t->pt.ass.right, -1, where); - ins.opcode = SET; + ins.opcode = OPC_SET; ins.u.set.l = var_l; ins.u.set.r = var_r; new_instr(ins, where); } -static int -new_cond_instr(int opcode, int left, int right, int pref_var, - struct list* where) -{ - struct code ins; - - ins.opcode = opcode; - ins.u.tpop.l = left; - ins.u.tpop.r = right; - if (pref_var >= 0) - ins.u.tpop.res = pref_var; - else - ins.u.tpop.res = current_varcode++;; - new_instr(ins, where); - return ins.u.tpop.res; -} - static int eval_cond(struct tree *t, int pref_var, struct list* where) { @@ -165,7 +164,35 @@ eval_cond(struct tree *t, int pref_var, struct list* where) switch (t->pt.cond.op) { case '>': - return new_cond_instr(GT, left, + return new_3par_instr (OPC_GT, left, + right, pref_var, where); + break; + case '<': + return new_3par_instr (OPC_LT, left, + right, pref_var, where); + break; + case CC('<','='): + return new_3par_instr (OPC_LE, left, + right, pref_var, where); + break; + case CC('>','='): + return new_3par_instr (OPC_GE, left, + right, pref_var, where); + break; + case CC('!','~'): + return new_3par_instr (OPC_NRE, left, + right, pref_var, where); + break; + case CC('~','~'): + return new_3par_instr (OPC_RE, left, + right, pref_var, where); + break; + case CC('=','='): + return new_3par_instr (OPC_EQ, left, + right, pref_var, where); + break; + case CC('!','='): + return new_3par_instr (OPC_NEQ, left, right, pref_var, where); break; /* fixme: do more of them */ @@ -176,13 +203,34 @@ eval_cond(struct tree *t, int pref_var, struct list* where) } } if (t->pt.cond.type == OP_BOOL) { + struct code ins; + left = eval_cond(t->pt.cond.left, -1, where); - right = eval_cond(t->pt.cond.right, -1, where); + if (t->pt.cond.op != '!') /* ! is unary */ + right = eval_cond(t->pt.cond.right, -1, where); switch (t->pt.cond.op) { case '&': - return new_cond_instr(AND, left, + return new_3par_instr (OPC_AND, left, + right, pref_var, where); + break; + case '|': + return new_3par_instr (OPC_OR, left, + right, pref_var, where); + break; + case '^': + return new_3par_instr (OPC_XOR, left, right, pref_var, where); break; + case '!': + ins.opcode = OPC_NOT; + ins.u.dpop.par = left; + if (pref_var >= 0) + ins.u.dpop.res = pref_var; + else + ins.u.dpop.res = current_varcode++;; + new_instr(ins, where); + return ins.u.dpop.res; + break; default: die("eval_cond: unknown boolean op %c\n", t->pt.cond.op); @@ -202,8 +250,8 @@ do_if(struct tree *t, struct list* where) list_init(if_branch); list_init(else_branch); - nop.opcode = NOP; - jmp.opcode = JUMP; + nop.opcode = OPC_NOP; + jmp.opcode = OPC_JUMP; c = eval_cond(t->pt.tif.c, -1, where); @@ -214,7 +262,7 @@ do_if(struct tree *t, struct list* where) jmp.u.jump.target = list_last(else_branch); new_instr(jmp, if_branch); - ins.opcode = JUMP_UNLESS; + ins.opcode = OPC_JUMP_UNLESS; ins.u.jump_unless.cond = c; ins.u.jump_unless.target = list_last(if_branch); new_instr(ins, where); @@ -231,8 +279,6 @@ do_arrow(struct tree* t, struct list* where) int v; struct code ins; - v = evaluate(t->pt.arrow.s, -1, where); - ins.u.arrow.what = v; if (t->pt.arrow.left == K_COPY) ins.u.arrow.copy = 1; @@ -240,23 +286,37 @@ do_arrow(struct tree* t, struct list* where) ins.u.arrow.copy = 0; switch (t->pt.arrow.right) { case K_EMPTY: - ins.opcode = STORE; + ins.opcode = OPC_DELIVER; break; case K_PIPE: - ins.opcode = PIPE; + ins.opcode = OPC_PIPE; break; case K_MAIL: - ins.opcode = MAIL; + ins.opcode = OPC_MAIL; + break; + case K_DISCARD: + ins.opcode = OPC_DISCARD; + break; + case K_FILTER: + ins.opcode = OPC_FILTER; break; default: die("do_arrow: This cannot happen ;-)"); } + + if (t->pt.arrow.right != K_DISCARD) { + v = evaluate(t->pt.arrow.s, -1, where); + ins.u.arrow.what = v; + } + new_instr(ins, where); } static void reset_temp_var_count(void) { + if (current_varcode > max_varcode) + max_varcode = current_varcode; current_varcode = temp_varcode_start; } @@ -291,8 +351,9 @@ compile(struct tree* t, struct list* where) eval_cond(t, -1, where); // warn? case ST_ARROW: do_arrow(t, where); + break; default: - die("compile: got to default"); + die("compile: got to default, type: %d", t->st); } } @@ -303,28 +364,85 @@ print_code(void) LIST_FOREACH(p, &input_code) { switch (p->opcode) { - case SET: + case OPC_SET: printf("SET %d %d\n", p->u.set.l, p->u.set.r); break; - case CAT: + case OPC_CAT: printf("CAT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); break; - case JUMP: + case OPC_JUMP: printf("JUMP %d\n", (int) p->u.jump.target); break; - case JUMP_UNLESS: + case OPC_JUMP_UNLESS: printf("JUMP_UNLESS %d %d\n", p->u.jump_unless.cond,(int) p->u.jump_unless.target); break; - case GT: + case OPC_GT: printf("GT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); break; - case AND: + case OPC_LT: + printf("LT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_LE: + printf("LE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_GE: + printf("GE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_RE: + printf("RE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_NRE: + printf("NRE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_NEQ: + printf("NEQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_EQ: + printf("EQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_AND: printf("AND %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); break; - case NOP: + case OPC_OR: + printf("OR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_XOR: + printf("XOR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_PLUS: + printf("PLUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_MINUS: + printf("MINUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_MUL: + printf("MUL %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_DIV: + printf("DIV %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); + break; + case OPC_NOT: + printf("NOT %d %d\n", p->u.dpop.par, p->u.dpop.res); + break; + case OPC_NOP: puts("NOP"); break; + case OPC_PIPE: + printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy); + break; + case OPC_FILTER: + printf("FILTER %d %d\n", p->u.arrow.what, p->u.arrow.copy); + break; + case OPC_DELIVER: + printf("DELIVER %d %d\n", p->u.arrow.what, p->u.arrow.copy); + break; + case OPC_MAIL: + printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy); + break; + case OPC_DISCARD: + puts("DISCARD"); + break; default: printf("not implemented, opcode: %d\n", p->opcode);