]> mj.ucw.cz Git - umpf.git/blobdiff - code.c
started with filtering mail
[umpf.git] / code.c
diff --git a/code.c b/code.c
index 7c2296829c80268d092fb0cdc0dcfa47fa008c41..59742fc9a8292c7241ca4241dafacacbdde840b6 100644 (file)
--- 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);