2022-01-02 16:19:54 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
#include "apfl.h"
|
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print(unsigned indent, FILE *out, struct apfl_value value)
|
|
|
|
|
{
|
2022-01-02 16:55:05 +00:00
|
|
|
struct apfl_string_view sv;
|
|
|
|
|
|
2022-01-02 16:19:54 +00:00
|
|
|
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:
|
2022-01-02 16:55:05 +00:00
|
|
|
sv = apfl_string_view_from(value.string);
|
|
|
|
|
apfl_print_indented(indent, out, "\"" APFL_STR_FMT "\"\n", APFL_STR_FMT_ARGS(sv));
|
2022-01-02 16:19:54 +00:00
|
|
|
return;
|
|
|
|
|
case APFL_VALUE_LIST:
|
2022-01-02 20:23:41 +00:00
|
|
|
if (value.list->len == 0) {
|
|
|
|
|
apfl_print_indented(indent, out, "[]\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-01-02 16:19:54 +00:00
|
|
|
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:
|
2022-01-04 20:22:46 +00:00
|
|
|
dst->string = apfl_refcounted_string_incref(src.string);
|
2022-01-02 16:19:54 +00:00
|
|
|
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:
|
2022-01-04 20:22:46 +00:00
|
|
|
apfl_refcounted_string_unref(value->string);
|
|
|
|
|
value->string = NULL;
|
2022-01-02 16:19:54 +00:00
|
|
|
goto ok;
|
|
|
|
|
case APFL_VALUE_LIST:
|
2022-01-02 16:55:05 +00:00
|
|
|
if (apfl_refcount_dec(&value->list->refcount)) {
|
2022-01-02 16:19:54 +00:00
|
|
|
DESTROY(value->list, apfl_list_deinit);
|
|
|
|
|
}
|
|
|
|
|
goto ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(false);
|
|
|
|
|
|
|
|
|
|
ok:
|
|
|
|
|
value->type = APFL_VALUE_NIL;
|
|
|
|
|
}
|