typedef enum ObjectType { OBJ_TYPE_FIXNUM, OBJ_TYPE_BOOL, OBJ_TYPE_NIL, OBJ_TYPE_SYMBOL, OBJ_TYPE_STRING, OBJ_TYPE_PAIR, OBJ_TYPE_PROCEDURE, OBJ_TYPE_ERR, } ObjectType; typedef struct Object { ObjectType type; union { // OBJ_TYPE_FIXNUM ssize_t fixnum; // OBJ_TYPE_STRING struct { char *string; size_t string_n; }; // OBJ_TYPE_PAIR struct { struct Object *car; struct Object *cdr; }; // OBJ_TYPE_SYMBOL struct { char *symbol; size_t symbol_n; }; // OBJ_TYPE_PROCEDURE struct Object *(*proc)(struct Object *args); }; } Object; // // Singletons. // static Object *obj_nil; static Object *obj_true; static Object *obj_false; static Object *obj_err; // // Constructors. // Object * alloc_object(ObjectType type) { Object *obj = malloc(sizeof(Object)); obj->type = type; return obj; } Object * make_fixnum(ssize_t num) { Object *obj = alloc_object(OBJ_TYPE_FIXNUM); obj->fixnum = num; return obj; } Object * make_procedure(Object *(*proc)(struct Object *args)) { Object *obj = alloc_object(OBJ_TYPE_PROCEDURE); obj->proc = proc; return obj; } Object * make_pair(Object *car, Object *cdr) { Object *obj = alloc_object(OBJ_TYPE_PAIR); obj->car = car; obj->cdr = cdr; return obj; } Object * make_symbol(StringView sv) { Object *obj = alloc_object(OBJ_TYPE_SYMBOL); obj->symbol = malloc(sizeof(char) * sv.n); memcpy(obj->symbol, sv.start, sv.n); obj->symbol_n = sv.n; return obj; } Object * make_string(void) { Object *obj = alloc_object(OBJ_TYPE_STRING); obj->string = NULL; obj->string_n = 0; return obj; } void append_string(Object *obj, const StringView sv) { assert(obj != NULL); assert(obj->type == OBJ_TYPE_STRING); if (sv.n == 0) { return; } obj->string = realloc(obj->string, (obj->string_n + sv.n) * sizeof(char)); memcpy(obj->string + obj->string_n, sv.start, sv.n); obj->string_n += sv.n; }