Lisp Value Functions


Our lval type is almost ready to go. Unlike the previous long type we have no current method for creating new instances of it. To do this we can declare two functions that construct an lval of either an error type or a number type.

  1. /* Create a new number type lval */
  2. lval lval_num(long x) {
  3. lval v;
  4. v.type = LVAL_NUM;
  5. v.num = x;
  6. return v;
  7. }
  8. /* Create a new error type lval */
  9. lval lval_err(int x) {
  10. lval v;
  11. v.type = LVAL_ERR;
  12. v.err = x;
  13. return v;
  14. }

These functions first create an lval called v, and assign the fields before returning it.

Because our lval function can now be one of two things we can no longer just use printf to output it. We will want to behave differently depending upon the type of the lval that is given. There is a concise way to do this in C using the switch statement. This takes some value as input and compares it to other known values, known as cases. When the values are equal it executes the code that follows up until the next break statement.

Using this we can build a function that can print an lval of any type like this.

  1. /* Print an "lval" */
  2. void lval_print(lval v) {
  3. switch (v.type) {
  4. /* In the case the type is a number print it */
  5. /* Then 'break' out of the switch. */
  6. case LVAL_NUM: printf("%li", v.num); break;
  7. /* In the case the type is an error */
  8. case LVAL_ERR:
  9. /* Check what type of error it is and print it */
  10. if (v.err == LERR_DIV_ZERO) {
  11. printf("Error: Division By Zero!");
  12. }
  13. if (v.err == LERR_BAD_OP) {
  14. printf("Error: Invalid Operator!");
  15. }
  16. if (v.err == LERR_BAD_NUM) {
  17. printf("Error: Invalid Number!");
  18. }
  19. break;
  20. }
  21. }
  22. /* Print an "lval" followed by a newline */
  23. void lval_println(lval v) { lval_print(v); putchar('\n'); }