#ifndef BDL_OBJECTS_H #define BDL_OBJECTS_H #include "string_view.h" #include "darray.h" typedef enum ObjectType { OBJ_TYPE_NIL, OBJ_TYPE_TRUE, OBJ_TYPE_FALSE, OBJ_TYPE_FIXNUM, OBJ_TYPE_SYMBOL, OBJ_TYPE_STRING, OBJ_TYPE_PAIR, OBJ_TYPE_LAMBDA, OBJ_TYPE_ERR, } ObjectType; struct Environment; typedef struct Object { ObjectType type; bool marked; union { // OBJ_TYPE_FIXNUM ssize_t fixnum; // OBJ_TYPE_STRING // OBJ_TYPE_SYMBOL struct { char *text; }; // OBJ_TYPE_PAIR // struct { // struct Object *car; // struct Object *cdr; // }; // OBJ_TYPE_LAMBDA // struct { // struct Object *params; // struct Object *body; // struct Environment *env; // }; }; } Object; void display(Object obj); // Value initialization. #define NIL_VAL ((Object){.type = OBJ_TYPE_NIL}) #define TRUE_VAL ((Object){.type = OBJ_TYPE_TRUE}) #define FALSE_VAL ((Object){.type = OBJ_TYPE_FALSE}) #define FIXNUM_VAL(VAL) ((Object){.type = OBJ_TYPE_FIXNUM, .fixnum = VAL}) #define BOOL_VAL(VAL) ((VAL) ? TRUE_VAL : FALSE_VAL) // Value extraction. #define AS_FIXNUM(VAL) ((VAL).fixnum) // Type checking. #define IS_TRUE(VAL) ((VAL).type != OBJ_TYPE_FALSE) #define IS_FALSE(VAL) ((VAL).type == OBJ_TYPE_FALSE) #define IS_FIXNUM(VAL) ((VAL).type == OBJ_TYPE_FIXNUM) #define IS_STRING(VAL) ((VAL).type == OBJ_TYPE_STRING) #define IS_SYMBOL(VAL) ((VAL).type == OBJ_TYPE_SYMBOL) Object make_string(StringView sv) { Object obj = { .type = OBJ_TYPE_STRING, .text = NULL, }; array_init(obj.text, sv.n); array_insert(obj.text, sv.start, sv.n); return obj; } Object make_symbol(StringView sv) { Object obj = { .type = OBJ_TYPE_SYMBOL, .text = NULL, }; array_init(obj.text, sv.n); array_insert(obj.text, sv.start, sv.n); return obj; } void display(Object obj) { switch (obj.type) { case OBJ_TYPE_FIXNUM: { printf("%zd", obj.fixnum); } break; case OBJ_TYPE_TRUE: { printf("true"); } break; case OBJ_TYPE_FALSE: { printf("false"); } break; case OBJ_TYPE_NIL: { printf("()"); } break; case OBJ_TYPE_STRING: { printf("\"%.*s\"", (int)array_size(obj.text), obj.text); } break; case OBJ_TYPE_SYMBOL: { printf(":%.*s", (int)array_size(obj.text), obj.text); } break; case OBJ_TYPE_PAIR: { // printf("("); // display_pair(obj); // printf(")"); } break; case OBJ_TYPE_LAMBDA: { printf("#{procedure}"); } break; case OBJ_TYPE_ERR: { printf("#{error}"); } break; } return; } void object_free(Object obj) { if (IS_STRING(obj) || IS_SYMBOL(obj)) { array_free(obj.text); } } bool object_equal(Object a, Object b) { if (a.type != b.type) { return false; } switch (a.type) { case OBJ_TYPE_TRUE: case OBJ_TYPE_FALSE: { return true; } break; case OBJ_TYPE_FIXNUM: { return a.fixnum == b.fixnum; } break; case OBJ_TYPE_SYMBOL: case OBJ_TYPE_STRING: { if (array_size(a.text) != array_size(b.text)) { return false; } for (size_t i = 0; i < array_size(a.text); i++) { if (a.text[i] != b.text[i]) { return false; } } } break; default: { return false; } break; } return true; } #endif // BDL_OBJECTS_H