Equality


Equality is going to be different to ordering because we want it to work on more than number types. It will be useful to see if an input is equal to an empty list, or to see if two functions passed in are the same. Therefore we need to define a function which can test for equality between two different types of lval.

This function essentially checks that all the fields which make up the data for a particular lval type are equal. If all the fields are equal, the whole thing is considered equal. Otherwise if there are any differences the whole thing is considered unequal.

  1. int lval_eq(lval* x, lval* y) {
  2. /* Different Types are always unequal */
  3. if (x->type != y->type) { return 0; }
  4. /* Compare Based upon type */
  5. switch (x->type) {
  6. /* Compare Number Value */
  7. case LVAL_NUM: return (x->num == y->num);
  8. /* Compare String Values */
  9. case LVAL_ERR: return (strcmp(x->err, y->err) == 0);
  10. case LVAL_SYM: return (strcmp(x->sym, y->sym) == 0);
  11. /* If builtin compare, otherwise compare formals and body */
  12. case LVAL_FUN:
  13. if (x->builtin || y->builtin) {
  14. return x->builtin == y->builtin;
  15. } else {
  16. return lval_eq(x->formals, y->formals)
  17. && lval_eq(x->body, y->body);
  18. }
  19. /* If list compare every individual element */
  20. case LVAL_QEXPR:
  21. case LVAL_SEXPR:
  22. if (x->count != y->count) { return 0; }
  23. for (int i = 0; i < x->count; i++) {
  24. /* If any element not equal then whole list not equal */
  25. if (!lval_eq(x->cell[i], y->cell[i])) { return 0; }
  26. }
  27. /* Otherwise lists must be equal */
  28. return 1;
  29. break;
  30. }
  31. return 0;
  32. }

Using this function the new builtin function for equality comparison is very simple to add. We simply ensure two arguments are input, and that they are equal. We store the result of the comparison into a new lval and return it.

  1. lval* builtin_cmp(lenv* e, lval* a, char* op) {
  2. LASSERT_NUM(op, a, 2);
  3. int r;
  4. if (strcmp(op, "==") == 0) {
  5. r = lval_eq(a->cell[0], a->cell[1]);
  6. }
  7. if (strcmp(op, "!=") == 0) {
  8. r = !lval_eq(a->cell[0], a->cell[1]);
  9. }
  10. lval_del(a);
  11. return lval_num(r);
  12. }
  13. lval* builtin_eq(lenv* e, lval* a) {
  14. return builtin_cmp(e, a, "==");
  15. }
  16. lval* builtin_ne(lenv* e, lval* a) {
  17. return builtin_cmp(e, a, "!=");
  18. }