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.
/* Create a new number type lval */
lval lval_num(long x) {
lval v;
v.type = LVAL_NUM;
v.num = x;
return v;
}
/* Create a new error type lval */
lval lval_err(int x) {
lval v;
v.type = LVAL_ERR;
v.err = x;
return v;
}
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.
/* Print an "lval" */
void lval_print(lval v) {
switch (v.type) {
/* In the case the type is a number print it */
/* Then 'break' out of the switch. */
case LVAL_NUM: printf("%li", v.num); break;
/* In the case the type is an error */
case LVAL_ERR:
/* Check what type of error it is and print it */
if (v.err == LERR_DIV_ZERO) {
printf("Error: Division By Zero!");
}
if (v.err == LERR_BAD_OP) {
printf("Error: Invalid Operator!");
}
if (v.err == LERR_BAD_NUM) {
printf("Error: Invalid Number!");
}
break;
}
}
/* Print an "lval" followed by a newline */
void lval_println(lval v) { lval_print(v); putchar('\n'); }