static void test_param() { Expr *e = NULL; int i = 12345; double d = 12.345; long long l = 9223372036854775807LL; char *s = "string_1"; Arg arg; arg.vals[0].v_int = i; arg.vals[1].v_real = d; arg.vals[2].v_long = l; str_cpy(arg.vals[3].v_str, s); e = expr_eq(expr_int(i), expr_param(0, Int)); if (expr_bool_val(e, NULL, &arg) == 0) fail(); expr_free(e); e = expr_eq(expr_real(d), expr_param(1, Real)); if (expr_bool_val(e, NULL, &arg) == 0) fail(); expr_free(e); e = expr_eq(expr_long(l), expr_param(2, Long)); if (expr_bool_val(e, NULL, &arg) == 0) fail(); expr_free(e); e = expr_eq(expr_str(s), expr_param(3, String)); if (expr_bool_val(e, NULL, &arg) == 0) fail(); expr_free(e); }
void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) { #define e1 (*ep1) #define e2 (*ep2) if (e1->type == type) { expr_extract_eq(type, ep, &e1->left.expr, &e2); expr_extract_eq(type, ep, &e1->right.expr, &e2); return; } if (e2->type == type) { expr_extract_eq(type, ep, ep1, &e2->left.expr); expr_extract_eq(type, ep, ep1, &e2->right.expr); return; } if (expr_eq(e1, e2)) { *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; expr_free(e2); if (type == E_AND) { e1 = expr_alloc_symbol(&symbol_yes); e2 = expr_alloc_symbol(&symbol_yes); } else if (type == E_OR) { e1 = expr_alloc_symbol(&symbol_no); e2 = expr_alloc_symbol(&symbol_no); } } #undef e1 #undef e2 }
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) { if (e1->type == type) { __expr_eliminate_eq(type, &e1->left.expr, &e2); __expr_eliminate_eq(type, &e1->right.expr, &e2); return; } if (e2->type == type) { __expr_eliminate_eq(type, &e1, &e2->left.expr); __expr_eliminate_eq(type, &e1, &e2->right.expr); return; } if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && e1->left.sym == e2->left.sym && (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) return; if (!expr_eq(e1, e2)) return; trans_count++; expr_free(e1); expr_free(e2); switch (type) { case E_OR: e1 = expr_alloc_symbol(&symbol_no); e2 = expr_alloc_symbol(&symbol_no); break; case E_AND: e1 = expr_alloc_symbol(&symbol_yes); e2 = expr_alloc_symbol(&symbol_yes); break; default: ; } }
static void test_conv_eval(Expr *l, Expr *r) { Expr *e = expr_eq(l, r); if (!expr_bool_val(e, NULL, NULL)) fail(); expr_free(e); }
static void test_select() { int a, b, c; Type ta, tb, tc; Rel *src = load("select_1"); head_attr(src->head, "b", &b, &tb); Expr *expr = expr_eq(expr_real(1.01), expr_attr(b, tb)); Rel *r = rel_select(src, expr); if (!equal(r, "select_1_res")) fail(); src = load("select_2"); head_attr(src->head, "a", &a, &ta); head_attr(src->head, "b", &b, &tb); head_attr(src->head, "c", &c, &tc); expr = expr_or(expr_gt(expr_attr(b, tb), expr_real(4.00)), expr_lt(expr_attr(a, ta), expr_int(2))); expr = expr_or(expr, expr_lt(expr_attr(c, tc), expr_str("aab"))); r = rel_select(src, expr); if (!equal(r, "select_2_res")) fail(); src = load("select_3"); head_attr(src->head, "a", &a, &ta); head_attr(src->head, "b", &b, &tb); expr = expr_and(expr_not(expr_attr(a, ta)), expr_not(expr_eq(expr_attr(b, tb), expr_real(1.01)))); r = rel_select(src, expr); if (!equal(r, "select_3_res")) fail(); }
static int expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; if (e1->type != e2->type) return 0; switch (e1->type) { case E_EQUAL: case E_GEQ: case E_GTH: case E_LEQ: case E_LTH: case E_UNEQUAL: return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; case E_SYMBOL: return e1->left.sym == e2->left.sym; case E_NOT: return expr_eq(e1->left.expr, e2->left.expr); case E_AND: case E_OR: e1 = expr_copy(e1); e2 = expr_copy(e2); old_count = trans_count; expr_eliminate_eq(&e1, &e2); res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && e1->left.sym == e2->left.sym); expr_free(e1); expr_free(e2); trans_count = old_count; return res; case E_LIST: case E_RANGE: case E_NONE: /* panic */; } if (DEBUG_EXPR) { expr_fprint(e1, stdout); printf(" = "); expr_fprint(e2, stdout); printf(" ?\n"); } return 0; }
int expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; if (e1->type != e2->type) return 0; switch (e1->type) { case E_EQUAL: case E_UNEQUAL: return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; case E_SYMBOL: return e1->left.sym == e2->left.sym; case E_NOT: return expr_eq(e1->left.expr, e2->left.expr); case E_AND: case E_OR: e1 = expr_copy(e1); e2 = expr_copy(e2); old_count = trans_count; expr_eliminate_eq(&e1, &e2); res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && e1->left.sym == e2->left.sym); expr_free(e1); expr_free(e2); trans_count = old_count; return res; case E_CHOICE: case E_NONE: /* panic */ ; } print_expr(0, e1, 0); printf(" = "); print_expr(0, e2, 0); printf(" ?\n"); return 0; }
static void test_attr() { Head *h = gen_head(); int i = 1; char *s = "string_1"; Value vals[2]; vals[0] = val_new_int(&i); vals[1] = val_new_str(s); Tuple *t = tuple_new(vals, 2); int pos; Type type; head_attr(h, "c", &pos, &type); Expr *e = expr_eq(expr_str("string_1"), expr_attr(pos, type)); if (expr_bool_val(e, t, NULL) == 0) fail(); expr_free(e); tuple_free(t); mem_free(h); }
/* * Given expression `e1' and `e2', returns the leaf of the longest * sub-expression of `e1' not containing 'e2. */ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) { struct expr *ret; switch (e1->type) { case E_OR: return expr_alloc_and( expr_simplify_unmet_dep(e1->left.expr, e2), expr_simplify_unmet_dep(e1->right.expr, e2)); case E_AND: { struct expr *e; e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); e = expr_eliminate_dups(e); ret = (!expr_eq(e, e1)) ? e1 : NULL; expr_free(e); break; } default: ret = e1; break; } return expr_get_leftmost_symbol(ret); }
static struct expr *expr_join_and(struct expr *e1, struct expr *e2) { struct expr *tmp; struct symbol *sym1, *sym2; if (expr_eq(e1, e2)) return expr_copy(e1); if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) return NULL; if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) return NULL; if (e1->type == E_NOT) { tmp = e1->left.expr; if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) return NULL; sym1 = tmp->left.sym; } else sym1 = e1->left.sym; if (e2->type == E_NOT) { if (e2->left.expr->type != E_SYMBOL) return NULL; sym2 = e2->left.expr->left.sym; } else sym2 = e2->left.sym; if (sym1 != sym2) return NULL; if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) return NULL; if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) // (a) && (a='y') -> (a='y') return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) // (a) && (a!='n') -> (a) return expr_alloc_symbol(sym1); if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) // (a) && (a!='m') -> (a='y') return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); if (sym1->type == S_TRISTATE) { if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' sym2 = e1->right.sym; if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) : expr_alloc_symbol(&symbol_no); } if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' sym2 = e2->right.sym; if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) : expr_alloc_symbol(&symbol_no); } if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) // (a!='y') && (a!='n') -> (a='m') return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) // (a!='y') && (a!='m') -> (a='n') return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) // (a!='m') && (a!='n') -> (a='m') return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) return NULL; } if (DEBUG_EXPR) { printf("optimize ("); expr_fprint(e1, stdout); printf(") && ("); expr_fprint(e2, stdout); printf(")?\n"); } return NULL; }
/* * e1 || e2 -> ? */ struct expr * expr_join_or(struct expr *e1, struct expr *e2) { struct expr *tmp; struct symbol *sym1, *sym2; if (expr_eq(e1, e2)) return expr_copy(e1); if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) return NULL; if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) return NULL; if (e1->type == E_NOT) { tmp = e1->left.expr; if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) return NULL; sym1 = tmp->left.sym; } else sym1 = e1->left.sym; if (e2->type == E_NOT) { if (e2->left.expr->type != E_SYMBOL) return NULL; sym2 = e2->left.expr->left.sym; } else sym2 = e2->left.sym; if (sym1 != sym2) return NULL; if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) return NULL; if (sym1->type == S_TRISTATE) { if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { // (a='y') || (a='m') -> (a!='n') return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); } if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { // (a='y') || (a='n') -> (a!='m') return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); } if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { // (a='m') || (a='n') -> (a!='y') return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); } } if (sym1->type == S_BOOLEAN && sym1 == sym2) { if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) return expr_alloc_symbol(&symbol_yes); } printf("optimize "); print_expr(0, e1, 0); printf(" || "); print_expr(0, e2, 0); printf(" ?\n"); return NULL; }
static void test_cmp_ops() { Expr *e_eq = expr_eq(expr_str("hello world"), expr_str("hello world")); Expr *e_neq = expr_eq(expr_str("hello world"), expr_str("hello world2")); Expr *e_lt = expr_lt(expr_str("BacvfebG"), expr_str("Bacvfebg")); Expr *e_gt = expr_gt(expr_str("BacvfebG"), expr_str("BacvfeaG")); Expr *e_ngt = expr_gt(expr_str("hello world!"), expr_str("hello world!")); Expr *e_gte = expr_gte(expr_str("hello world!"), expr_str("hello world!")); Expr *e_lte = expr_lte(expr_str("hello world!"), expr_str("hello world!")); Expr *e_ngte = expr_gte(expr_str("hello a"), expr_str("hello world!")); Expr *e_nlte = expr_lte(expr_str("hello world!"), expr_str("hello a")); if (!expr_bool_val(e_eq, NULL, NULL)) fail(); if (expr_bool_val(e_neq, NULL, NULL)) fail(); if (!expr_bool_val(e_gt, NULL, NULL)) fail(); if (!expr_bool_val(e_lt, NULL, NULL)) fail(); if (expr_bool_val(e_ngt, NULL, NULL)) fail(); if (!expr_bool_val(e_gte, NULL, NULL)) fail(); if (!expr_bool_val(e_lte, NULL, NULL)) fail(); if (expr_bool_val(e_ngte, NULL, NULL)) fail(); if (expr_bool_val(e_nlte, NULL, NULL)) fail(); expr_free(e_eq); expr_free(e_neq); expr_free(e_lt); expr_free(e_gt); expr_free(e_ngt); expr_free(e_gte); expr_free(e_lte); expr_free(e_ngte); expr_free(e_nlte); e_gte = expr_gte(expr_real(0.9), expr_real(0.5)); e_lte = expr_lte(expr_int(-1), expr_int(1)); if (!expr_bool_val(e_gte, NULL, NULL)) fail(); if (!expr_bool_val(e_lte, NULL, NULL)) fail(); expr_free(e_gte); expr_free(e_lte); }