apfl/src/value.c

124 lines
2.7 KiB
C
Raw Normal View History

#include <assert.h>
#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;
}