From 0dc94edb85ce7d4f6972a5a2339e7500a9a30dbe Mon Sep 17 00:00:00 2001 From: Anicka Bernathova Date: Wed, 15 Jul 2009 16:20:37 +0200 Subject: [PATCH] add more binary operators --- code.c | 140 ++++++++++++++++++++++++++++++++++++--------------------- cond.y | 18 +++++--- umpf.h | 46 +++++++++++++------ 3 files changed, 135 insertions(+), 69 deletions(-) diff --git a/code.c b/code.c index 04b41b3..070f783 100644 --- a/code.c +++ b/code.c @@ -80,14 +80,29 @@ 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) { @@ -96,15 +111,8 @@ evaluate(struct tree* t, int pref_var, struct list* 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; + return new_3par_instr(OPC_CAT, left, + right, pref_var, where); break; default: die("evaluate: got to default"); @@ -122,30 +130,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 +156,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 +195,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 +242,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 +254,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 +278,16 @@ 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_STORE; 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; default: die("do_arrow: This cannot happen ;-)"); @@ -311,38 +351,38 @@ 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_AND: printf("AND %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res); break; - case NOP: + 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: + case OPC_STORE: printf("STORE %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: diff --git a/cond.y b/cond.y index 5d5751b..ec5bc8e 100644 --- a/cond.y +++ b/cond.y @@ -27,9 +27,9 @@ static struct tree* tree_malloc(int type); %left ARROW %left EQ NEQ GE LE '<' '>' RE NRE %left '=' -%left '.' -%left '+' '-' -%left '*' '/' +%left '.' +%left '+' '-' +%left '*' '/' %left '|' %left '^' %left '&' @@ -43,6 +43,7 @@ static struct tree* tree_malloc(int type); %type arrow %type cond %type rop +%type bop %type left %type right %type leaves @@ -196,14 +197,21 @@ right: /* empty */ { $$ = K_EMPTY; } ; ass_right: leaves - | ass_right '.' ass_right { + | ass_right bop ass_right { $$ = tree_malloc(ST_OP); - $$->pt.op.op = '.'; + $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } ; +bop: '.' {$$ = $1} + | '+' {$$ = $1} + | '-' {$$ = $1} + | '*' {$$ = $1} + | '/' {$$ = $1} +; + %% struct tree* diff --git a/umpf.h b/umpf.h index c7d59a1..946279e 100644 --- a/umpf.h +++ b/umpf.h @@ -128,20 +128,34 @@ char* cat(char* l, char* r); struct code { struct node car; enum { - SET, - JUMP, - JUMP_IF, - JUMP_UNLESS, - DELIVER, - CALL_EXT, - NOP, - CAT, - GT, - AND, - PIPE, - MAIL, - STORE, - DISCARD + OPC_SET, + OPC_JUMP, + OPC_JUMP_IF, + OPC_JUMP_UNLESS, + OPC_DELIVER, + OPC_CALL_EXT, + OPC_NOP, + OPC_CAT, + OPC_GT, + OPC_LT, + OPC_LE, + OPC_GE, + OPC_EQ, + OPC_NEQ, + OPC_RE, + OPC_NRE, + OPC_AND, + OPC_OR, + OPC_XOR, + OPC_NOT, + OPC_PLUS, + OPC_MINUS, + OPC_MUL, + OPC_DIV, + OPC_PIPE, + OPC_MAIL, + OPC_STORE, + OPC_DISCARD } opcode; union { @@ -165,6 +179,10 @@ struct code { int r; int res; /* result */ } tpop; + struct { + int par; + int res; /* result */ + } dpop; struct { int copy; int what; -- 2.39.2