Mercurial > hg-old > index.cgi
diff lwlib/lw_expr.c @ 371:9c24d9d485b9
Much bugfixing
author | lost@starbug |
---|---|
date | Wed, 21 Apr 2010 23:29:18 -0600 |
parents | 6b33faa21a0a |
children | 90de73ba0cac |
line wrap: on
line diff
--- a/lwlib/lw_expr.c Tue Apr 20 21:59:58 2010 -0600 +++ b/lwlib/lw_expr.c Wed Apr 21 23:29:18 2010 -0600 @@ -171,7 +171,8 @@ r -> type = lw_expr_type_oper; r -> value = t; lw_expr_add_operand(r, te1); - lw_expr_add_operand(r, te2); + if (te2) + lw_expr_add_operand(r, te2); break; default: @@ -206,7 +207,10 @@ switch (E -> type) { case lw_expr_type_int: - fprintf(fp, "%d ", E -> value); + if (E -> value < 0) + fprintf(fp, "-%#x ", -(E -> value)); + else + fprintf(fp, "%#x ", E -> value); break; case lw_expr_type_var: @@ -337,9 +341,17 @@ void lw_expr_simplify_sortconstfirst(lw_expr_t E) { struct lw_expr_opers *o; - + + if (E -> type != lw_expr_type_oper) + return; + if (E -> value != lw_expr_oper_times && E -> value != lw_expr_oper_plus) + return; + for (o = E -> operands; o; o = o -> next) - lw_expr_simplify_sortconstfirst(o -> p); + { + if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus)) + lw_expr_simplify_sortconstfirst(o -> p); + } for (o = E -> operands; o; o = o -> next) { @@ -380,10 +392,93 @@ return 1; } +int lw_expr_simplify_isliketerm(lw_expr_t e1, lw_expr_t e2) +{ + fprintf(stderr, "isliketerm in: "); + lw_expr_print(e1, stderr); + fprintf(stderr, "; "); + lw_expr_print(e2, stderr); + fprintf(stderr, "\n"); + + // first term is a "times" + if (e1 -> type == lw_expr_type_oper && e1 -> value == lw_expr_oper_times) + { + // second term is a "times" + if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times) + { + // both times - easy check + struct lw_expr_opers *o1, *o2; + for (o1 = e1 -> operands; o1; o1 = o1 -> next) + if (o1 -> p -> type != lw_expr_type_int) + break; + + for (o2 = e2 -> operands; o2; o2 = o2 -> next) + if (o2 -> p -> type != lw_expr_type_int) + break; + + if (lw_expr_simplify_compareoperandlist(&o1, &o2)) + return 1; + return 0; + } + + // not a times - have to assume it's the operand list + // with a "1 *" in front if it + if (e1 -> operands -> next -> next) + return 0; + if (!lw_expr_compare(e1 -> operands -> next -> p, e2)) + return 0; + return 1; + } + + // e1 is not a times + if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times) + { + // e2 is a times + if (e2 -> operands -> next -> next) + return 0; + if (!lw_expr_compare(e1, e2 -> operands -> next -> p)) + return 0; + return 1; + } + + // neither are times + if (!lw_expr_compare(e1, e2)) + return 0; + return 1; +} + void lw_expr_simplify(lw_expr_t E, void *priv) { struct lw_expr_opers *o; + // replace subtraction with O1 + -1(O2)... + // needed for like term collection + if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_minus) + { + for (o = E -> operands -> next; o; o = o -> next) + { + lw_expr_t e1, e2; + + e2 = lw_expr_build(lw_expr_type_int, -1); + e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, e2, o -> p); + lw_expr_destroy(o -> p); + lw_expr_destroy(e2); + o -> p = e1; + } + E -> value = lw_expr_oper_plus; + } + + // turn "NEG" into -1(O) - needed for like term collection + if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_neg) + { + lw_expr_t e1; + + E -> value = lw_expr_oper_times; + e1 = lw_expr_build(lw_expr_type_int, -1); + lw_expr_add_operand(E, e1); + lw_expr_destroy(e1); + } + again: // try to resolve non-constant terms to constants here if (E -> type == lw_expr_type_special && evaluate_special) @@ -442,8 +537,65 @@ if (E -> type != lw_expr_type_oper) return; - // sort "constants" to the start of each operand list for + and * - lw_expr_simplify_sortconstfirst(E); + // merge plus operations + if (E -> value == lw_expr_oper_plus) + { + lw_expr_t e2; + + tryagainplus: + for (o = E -> operands; o; o = o -> next) + { + if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus) + { + struct lw_expr_opers *o2, *o3; + // we have a + operation - bring operands up + + for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) + /* do nothing */ ; + if (o2) + o2 -> next = o -> p -> operands; + else + E -> operands = o -> p -> operands; + for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) + /* do nothing */ ; + o2 -> next = o -> next; + o -> p -> operands = NULL; + lw_expr_destroy(o -> p); + lw_free(o); + goto tryagainplus; + } + } + } + + // merge times operations + if (E -> value == lw_expr_oper_times) + { + lw_expr_t e2; + + tryagaintimes: + for (o = E -> operands; o; o = o -> next) + { + if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) + { + struct lw_expr_opers *o2, *o3; + // we have a + operation - bring operands up + + for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) + /* do nothing */ ; + if (o2) + o2 -> next = o -> p -> operands; + else + E -> operands = o -> p -> operands; + for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) + /* do nothing */ ; + o2 -> next = o -> next; + o -> p -> operands = NULL; + lw_expr_destroy(o -> p); + lw_free(o); + goto tryagaintimes; + } + } + } // simplify operands for (o = E -> operands; o; o = o -> next) @@ -534,6 +686,56 @@ return; } + if (E -> value == lw_expr_oper_plus) + { + lw_expr_t e1; + int cval = 0; + + e1 = lw_expr_create(); + e1 -> operands = E -> operands; + E -> operands = 0; + + for (o = e1 -> operands; o; o = o -> next) + { + if (o -> p -> type == lw_expr_type_int) + cval += o -> p -> value; + else + lw_expr_add_operand(E, o -> p); + } + lw_expr_destroy(e1); + if (cval) + { + e1 = lw_expr_build(lw_expr_type_int, cval); + lw_expr_add_operand(E, e1); + lw_expr_destroy(e1); + } + } + + if (E -> value == lw_expr_oper_times) + { + lw_expr_t e1; + int cval = 1; + + e1 = lw_expr_create(); + e1 -> operands = E -> operands; + E -> operands = 0; + + for (o = e1 -> operands; o; o = o -> next) + { + if (o -> p -> type == lw_expr_type_int) + cval *= o -> p -> value; + else + lw_expr_add_operand(E, o -> p); + } + lw_expr_destroy(e1); + if (cval != 1) + { + e1 = lw_expr_build(lw_expr_type_int, cval); + lw_expr_add_operand(E, e1); + lw_expr_destroy(e1); + } + } + if (E -> value == lw_expr_oper_times) { for (o = E -> operands; o; o = o -> next) @@ -555,35 +757,74 @@ } } + // sort "constants" to the start of each operand list for + and * + if (E -> value == lw_expr_oper_plus || E -> value == lw_expr_oper_times) + lw_expr_simplify_sortconstfirst(E); + // look for like terms and collect them together if (E -> value == lw_expr_oper_plus) { + struct lw_expr_opers *o2; for (o = E -> operands; o; o = o -> next) { - if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) + // skip constants + if (o -> p -> type == lw_expr_type_int) + continue; + + // we have a term to match + // (o -> p) is first term + for (o2 = o -> next; o2; o2 = o2 -> next) { - // we have a "times" here - // find first non-const operand - struct lw_expr_opers *op1, *op2, *o2; - for (op1 = o -> p -> operands; op1; op1 = op1 -> next) - if (op1 -> p -> type != lw_expr_type_int) - break; + lw_expr_t e1, e2; - for (o2 = o -> next; o2; o2 = o2 -> next) + if (o2 -> p -> type == lw_expr_type_int) + continue; + + if (lw_expr_simplify_isliketerm(o -> p, o2 -> p)) { + int coef, coef2; + + // we have a like term here + // do something about it + if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) + { + if (o -> p -> operands -> p -> type == lw_expr_type_int) + coef = o -> p -> operands -> p -> value; + else + coef = 1; + } + else + coef = 1; if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times) { - // another "times" - for (op2 = o2 -> p -> operands; op2; op2 = op2 -> next) - if (op2 -> p -> type != lw_expr_type_int) - break; - - if (lw_expr_simplify_compareoperandlist(&op1, &op2)) - { - // we have like terms here - // do something about it - } + if (o2 -> p -> operands -> p -> type == lw_expr_type_int) + coef2 = o2 -> p -> operands -> p -> value; + else + coef2 = 1; } + else + coef2 = 1; + coef += coef2; + e1 = lw_expr_create(); + e1 -> type = lw_expr_type_oper; + e1 -> value = lw_expr_oper_times; + if (coef != 1) + { + e2 = lw_expr_build(lw_expr_type_int, coef); + lw_expr_add_operand(e1, e2); + lw_expr_destroy(e2); + } + lw_expr_destroy(o -> p); + o -> p = e1; + for (o = o2 -> p -> operands; o; o = o -> next) + { + if (o -> p -> type == lw_expr_type_int) + continue; + lw_expr_add_operand(e1, o -> p); + } + lw_expr_destroy(o2 -> p); + o2 -> p = lw_expr_build(lw_expr_type_int, 0); + goto again; } } }