Function Type
As we’ve added a new possible lval
type with the enumeration LVAL_FUN
. We should update all our relevant functions that work on lvals
to deal correctly with this update. In most cases this just means inserting new cases into switch statements.
We can start by making a new constructor function for this type.
lval* lval_fun(lbuiltin func) {
lval* v = malloc(sizeof(lval));
v->type = LVAL_FUN;
v->fun = func;
return v;
}
On deletion we don’t need to do anything special for function pointers.
case LVAL_FUN: break;
On printing we can just print out a nominal string.
case LVAL_FUN: printf("<function>"); break;
We’re also going to add a new function for copying an lval
. This is going to come in useful when we put things into, and take things out of, the environment. For numbers and functions we can just copy the relevant fields directly. For strings we need to copy using malloc
and strcpy
. To copy lists we need to allocate the correct amount of space and then copy each element individually.
lval* lval_copy(lval* v) {
lval* x = malloc(sizeof(lval));
x->type = v->type;
switch (v->type) {
/* Copy Functions and Numbers Directly */
case LVAL_FUN: x->fun = v->fun; break;
case LVAL_NUM: x->num = v->num; break;
/* Copy Strings using malloc and strcpy */
case LVAL_ERR:
x->err = malloc(strlen(v->err) + 1);
strcpy(x->err, v->err); break;
case LVAL_SYM:
x->sym = malloc(strlen(v->sym) + 1);
strcpy(x->sym, v->sym); break;
/* Copy Lists by copying each sub-expression */
case LVAL_SEXPR:
case LVAL_QEXPR:
x->count = v->count;
x->cell = malloc(sizeof(lval*) * x->count);
for (int i = 0; i < x->count; i++) {
x->cell[i] = lval_copy(v->cell[i]);
}
break;
}
return x;
}