int exp_match_exp( sql_exp *e1, sql_exp *e2) { if (exp_match(e1, e2)) return 1; if (e1->type == e2->type) { switch(e1->type) { case e_cmp: if (e1->flag == e2->flag && !is_complex_exp(e1->flag) && exp_match_exp(e1->l, e2->l) && exp_match_exp(e1->r, e2->r) && ((!e1->f && !e2->f) || exp_match_exp(e1->f, e2->f))) return 1; else if (e1->flag == e2->flag && e1->flag == cmp_or && exp_match_list(e1->l, e2->l) && exp_match_list(e1->r, e2->r)) return 1; else if (e1->flag == e2->flag && (e1->flag == cmp_in || e1->flag == cmp_notin) && exp_match_exp(e1->l, e2->l) && exp_match_list(e1->r, e2->r)) return 1; break; case e_convert: if (!subtype_cmp(exp_totype(e1), exp_totype(e2)) && !subtype_cmp(exp_fromtype(e1), exp_fromtype(e2)) && exp_match_exp(e1->l, e2->l)) return 1; break; case e_aggr: if (!subaggr_cmp(e1->f, e2->f) && /* equal aggregation*/ exp_match_list(e1->l, e2->l) && e1->flag == e2->flag) return 1; break; case e_func: if (!subfunc_cmp(e1->f, e2->f) && /* equal functions */ exp_match_list(e1->l, e2->l)) return 1; break; case e_atom: if (e1->l && e2->l && !atom_cmp(e1->l, e2->l)) return 1; break; default: break; } } return 0; }
struct atom *builtin_eq(struct atom *expr, struct env *env) { struct list *list = expr->list; struct atom *op = LIST_FIRST(list); struct atom *a = CDR(op); struct atom *b = CDR(a); if (!a || !b) { printf("error: eq takes 2 arguments\n"); return &nil_atom; } a = eval(a, env); b = eval(b, env); if (atom_cmp(a, b)) return &true_atom; return &false_atom; }
static int atom_cmp(struct atom *a, struct atom *b) { if (ATOM_TYPE(a) != ATOM_TYPE(b)) return 0; if (IS_TRUE(a) && !IS_TRUE(b)) return 0; if (IS_FALSE(a) && !IS_FALSE(b)) return 0; if (IS_TRUE(b) && !IS_TRUE(a)) return 0; if (IS_FALSE(b) && !IS_FALSE(a)) return 0; if (IS_NIL(a) && !IS_NIL(b)) return 0; if (IS_NIL(b) && !IS_NIL(a)) return 0; int result = 1; switch (ATOM_TYPE(a)) { case ATOM_INT: if (a->l != b->l) result = 0; break; case ATOM_STR: case ATOM_SYMBOL: if (strcmp(a->str.str, b->str.str) != 0) result = 0; break; case ATOM_LIST: { struct atom *ai = LIST_FIRST(a->list); struct atom *bi = LIST_FIRST(b->list); while (ai && bi) { if (!atom_cmp(ai, bi)) { result = 0; break; } ai = LIST_NEXT(ai, entries); bi = LIST_NEXT(bi, entries); } if (ai != NULL || bi != NULL) result = 0; break; } } return result; }