X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=code.c;h=59742fc9a8292c7241ca4241dafacacbdde840b6;hb=43367dfb74d85a732b8973140a7b87a888b11902;hp=04b41b3acfb3fb9310ada0627933f46e6342c7ac;hpb=98d46a95ee04d0e7de9b24041b8fb6bfefeb9a91;p=umpf.git diff --git a/code.c b/code.c index 04b41b3..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); @@ -238,16 +286,19 @@ 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 = DISCARD; + ins.opcode = OPC_DISCARD; + break; + case K_FILTER: + ins.opcode = OPC_FILTER; break; default: die("do_arrow: This cannot happen ;-)"); @@ -264,6 +315,8 @@ do_arrow(struct tree* t, struct list* where) static void reset_temp_var_count(void) { + if (current_varcode > max_varcode) + max_varcode = current_varcode; current_varcode = temp_varcode_start; } @@ -311,38 +364,83 @@ 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 PIPE: + case OPC_PIPE: printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy); break; - case STORE: - printf("STORE %d %d\n", p->u.arrow.what, p->u.arrow.copy); + 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 MAIL: + case OPC_MAIL: printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy); break; - case DISCARD: + case OPC_DISCARD: puts("DISCARD"); break; default: