+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);
+}
+