#include #include "apfl.h" #include "internal.h" static void print(unsigned indent, FILE *out, struct apfl_value value) { struct apfl_string_view sv; switch (value.type) { case APFL_VALUE_NIL: apfl_print_indented(indent, out, "nil\n"); return; case APFL_VALUE_BOOLEAN: apfl_print_indented(indent, out, value.boolean ? "true\n" : "false\n"); return; case APFL_VALUE_NUMBER: apfl_print_indented(indent, out, "%f\n", value.number); return; case APFL_VALUE_STRING: sv = apfl_string_view_from(value.string); apfl_print_indented(indent, out, "\"" APFL_STR_FMT "\"\n", APFL_STR_FMT_ARGS(sv)); return; case APFL_VALUE_LIST: if (value.list->len == 0) { apfl_print_indented(indent, out, "[]\n"); return; } apfl_print_indented(indent, out, "[\n"); for (size_t i = 0; i < value.list->len; i++) { print(indent+1, out, value.list->items[i]); } apfl_print_indented(indent, out, "]\n"); return; } fprintf(out, "Unknown value? (%d)\n", (int)value.type); } bool apfl_value_copy(struct apfl_value *dst, struct apfl_value src) { *dst = src; switch (src.type) { case APFL_VALUE_NIL: case APFL_VALUE_BOOLEAN: case APFL_VALUE_NUMBER: // Nothing to do goto ok; case APFL_VALUE_STRING: dst->string = apfl_refcounted_string_incref(src.string); goto ok; case APFL_VALUE_LIST: assert(src.list != NULL); assert(dst->list == src.list); src.list->refcount++; goto ok; } assert(false); ok: return true; } void apfl_value_print(struct apfl_value value, FILE *out) { print(0, out, value); } struct apfl_list * apfl_list_new(void) { struct apfl_list *list = ALLOC(struct apfl_list); if (list == NULL) { return NULL; } *list = (struct apfl_list) { .refcount = 1, .items = NULL, .len = 0, .cap = 0, }; return list; } void apfl_list_deinit(struct apfl_list *list) { DEINIT_LIST(list->items, list->len, apfl_value_deinit); list->refcount = 0; list->cap = 0; } void apfl_value_deinit(struct apfl_value *value) { switch (value->type) { case APFL_VALUE_NIL: case APFL_VALUE_BOOLEAN: case APFL_VALUE_NUMBER: goto ok; case APFL_VALUE_STRING: apfl_refcounted_string_unref(value->string); value->string = NULL; goto ok; case APFL_VALUE_LIST: if (apfl_refcount_dec(&value->list->refcount)) { DESTROY(value->list, apfl_list_deinit); } goto ok; } assert(false); ok: value->type = APFL_VALUE_NIL; }