Cyclic Types
The lbuiltin
type references the lval
type and the lenv
type. This means that they should be declared first in the source file.
But we want to make a lbuiltin
field in our lval
struct so we can create function values. So therefore our lbuiltin
declaration must go before our lval
declaration. This leads to what is called a cyclic type dependency, where two types depend on each other.
We’ve come across this problem before with functions which depend on each other. The solution was to create a forward declaration which declared a function but left the body of it empty.
In C we can do exactly the same with types. First we declare two struct
types without a body. Secondly we typedef these to the names lval
and lenv
. Then we can define our lbuiltin
function pointer type. And finally we can define the body of our lval
struct. Now all our type issues are resolved and the compiler won’t complain any more.
/* Forward Declarations */
struct lval;
struct lenv;
typedef struct lval lval;
typedef struct lenv lenv;
/* Lisp Value */
enum { LVAL_ERR, LVAL_NUM, LVAL_SYM,
LVAL_FUN, LVAL_SEXPR, LVAL_QEXPR };
typedef lval*(*lbuiltin)(lenv*, lval*);
struct lval {
int type;
long num;
char* err;
char* sym;
lbuiltin fun;
int count;
lval** cell;
};