Ordering


For simplicity’s sake I’m going to re-use our number data type to represent the result of comparisons. I’ll make a rule similar to C, to say that any number that isn’t 0 evaluates to true in an if statement, while 0 always evaluates to false.

Therefore our ordering functions are a little like a simplified version of our arithmetic functions. They’ll only work on numbers, and we only want them to work on two arguments.

If these error conditions are met the maths is simple. We want to return a number lval either 0 or 1 depending on the equality comparison between the two input lval. We can use C’s comparison operators to do this. Like our arithmetic functions we’ll make use of a single function to do all of the comparisons.

First we check the error conditions, then we compare the numbers in each of the arguments to get some result. Finally we return this result as a number value.

  1. lval* builtin_gt(lenv* e, lval* a) {
  2. return builtin_ord(e, a, ">");
  3. }
  1. lval* builtin_lt(lenv* e, lval* a) {
  2. return builtin_ord(e, a, "<");
  3. }
  1. lval* builtin_ge(lenv* e, lval* a) {
  2. return builtin_ord(e, a, ">=");
  3. }
  1. lval* builtin_le(lenv* e, lval* a) {
  2. return builtin_ord(e, a, "<=");
  3. }
  1. lval* builtin_ord(lenv* e, lval* a, char* op) {
  2. LASSERT_NUM(op, a, 2);
  3. LASSERT_TYPE(op, a, 0, LVAL_NUM);
  4. LASSERT_TYPE(op, a, 1, LVAL_NUM);
  5. int r;
  6. if (strcmp(op, ">") == 0) {
  7. r = (a->cell[0]->num > a->cell[1]->num);
  8. }
  9. if (strcmp(op, "<") == 0) {
  10. r = (a->cell[0]->num < a->cell[1]->num);
  11. }
  12. if (strcmp(op, ">=") == 0) {
  13. r = (a->cell[0]->num >= a->cell[1]->num);
  14. }
  15. if (strcmp(op, "<=") == 0) {
  16. r = (a->cell[0]->num <= a->cell[1]->num);
  17. }
  18. lval_del(a);
  19. return lval_num(r);
  20. }