typedef enum ObjectType { OBJ_TYPE_FIXNUM, OBJ_TYPE_BOOL, OBJ_TYPE_NIL, OBJ_TYPE_SYMBOL, OBJ_TYPE_STRING, OBJ_TYPE_PAIR, OBJ_TYPE_PROCEDURE, } ObjectType; typedef struct Object { ObjectType type; union { // OBJ_TYPE_FIXNUM ssize_t fixnum; // OBJ_TYPE_BOOL bool boolean; // 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. // Object *obj_nil; Object *obj_true; Object *obj_false; // // Constructors. // Object * make_fixnum(ssize_t num) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_FIXNUM; obj->fixnum = num; return obj; } Object * make_boolean(bool b) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_BOOL; obj->boolean = b; return obj; } Object * make_empty_string(void) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_STRING; obj->string = NULL; obj->string_n = 0; return obj; } void append_string(Object *string, StringView sv) { assert(string != NULL); assert(string->type == OBJ_TYPE_STRING); if (sv.n == 0) { return; } string->string = realloc(string->string, (string->string_n + sv.n) * sizeof(char)); memcpy(string->string + string->string_n, sv.start, sv.n); string->string_n += sv.n; } Object * make_symbol(const char *str, size_t n) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_SYMBOL; obj->string = malloc(sizeof(char) * n); memcpy(obj->string, str, n); obj->string_n = n; return obj; } Object * make_empty_list(void) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_NIL; return obj; } Object * make_procedure(Object *(*proc)(struct Object *args)) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_PROCEDURE; obj->proc = proc; return obj; } Object * make_pair(Object *car, Object *cdr) { Object *obj = malloc(sizeof(Object)); obj->type = OBJ_TYPE_PAIR; obj->car = car; obj->cdr = cdr; return obj; } // // Comparative ops. // bool symbol_eq(Object *a, Object *b) { if (a->type != b->type || a->type != OBJ_TYPE_SYMBOL || a->symbol_n != b->symbol_n) { return false; } for (size_t i = 0; i < a->symbol_n; i++) { if (a->symbol[i] != b->symbol[i]) { return false; } } return true; } // // Utility macros. // #define MAKE_SYM(SYM) make_symbol((SYM), sizeof(SYM) - 1)