diff --git a/src/apfl.h b/src/apfl.h index 22722e2..74595f0 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -609,6 +609,8 @@ enum apfl_result apfl_push_bool(apfl_ctx, bool); enum apfl_result apfl_push_number(apfl_ctx, apfl_number); // Push a string onto the stack enum apfl_result apfl_push_string_view_copy(apfl_ctx, struct apfl_string_view); +// Push a constant string. +enum apfl_result apfl_push_const_string(apfl_ctx, const char *); // Create a new empty list on the stack enum apfl_result apfl_list_create(apfl_ctx, size_t initial_capacity); // Append a value to a list. The value will be dropped. diff --git a/src/context.c b/src/context.c index 1482bed..06d56a5 100644 --- a/src/context.c +++ b/src/context.c @@ -295,6 +295,15 @@ apfl_push_string_view_copy(apfl_ctx ctx, struct apfl_string_view sv) ) } +enum apfl_result +apfl_push_const_string(apfl_ctx ctx, const char *string) +{ + return apfl_stack_push(ctx, (struct apfl_value) { + .type = VALUE_CONST_STRING, + .const_string = apfl_string_view_from(string), + }) ? APFL_RESULT_OK : APFL_RESULT_ERR_FATAL; +} + enum apfl_result apfl_list_create(apfl_ctx ctx, size_t initial_cap) { diff --git a/src/value.c b/src/value.c index 28334b4..2b67ff8 100644 --- a/src/value.c +++ b/src/value.c @@ -75,6 +75,19 @@ apfl_dict_deinit(struct dict_header *header) apfl_hashmap_deinit(&header->map); } +static struct apfl_string_view +as_string_view(struct apfl_value value) +{ + switch (value.type) { + case VALUE_STRING: + return apfl_string_view_from(*value.string); + case VALUE_CONST_STRING: + return value.const_string; + default: + return (struct apfl_string_view) { .bytes = NULL, .len = 0 }; + } +} + static bool format(unsigned indent, struct apfl_format_writer w, struct apfl_value value, bool skip_first_indent) { @@ -91,8 +104,9 @@ format(unsigned indent, struct apfl_format_writer w, struct apfl_value value, bo TRY(apfl_format_put_number(w, value.number)); return true; case VALUE_STRING: + case VALUE_CONST_STRING: TRY(apfl_format_put_string(w, "\"")); - TRY(apfl_format_put_string(w, *value.string)); + TRY(apfl_format_put_string(w, as_string_view(value))); TRY(apfl_format_put_string(w, "\"")); return true; case VALUE_LIST: @@ -205,23 +219,21 @@ dict_eq(const apfl_dict a, const apfl_dict b) bool apfl_value_eq(const struct apfl_value a, const struct apfl_value b) { - if (a.type != b.type) { - return false; - } - switch (a.type) { case VALUE_NIL: - return true; + return b.type == VALUE_NIL && true; case VALUE_BOOLEAN: - return a.boolean == b.boolean; + return b.type == VALUE_BOOLEAN && a.boolean == b.boolean; case VALUE_NUMBER: - return a.number == b.number; + return b.type == VALUE_NUMBER && a.number == b.number; case VALUE_STRING: - return a.string == b.string || apfl_string_eq(*a.string, *b.string); + case VALUE_CONST_STRING: + return (b.type == VALUE_STRING || b.type == VALUE_CONST_STRING) + && apfl_string_eq(as_string_view(a), as_string_view(b)); case VALUE_LIST: - return list_eq(a.list, b.list); + return b.type == VALUE_LIST && list_eq(a.list, b.list); case VALUE_DICT: - return dict_eq(a.dict, b.dict); + return b.type == VALUE_DICT && dict_eq(a.dict, b.dict); } assert(false); @@ -463,7 +475,8 @@ apfl_value_hash(const struct apfl_value value) case VALUE_NUMBER: return apfl_hash_fnv1a_add(&value.number, sizeof(apfl_number), hash); case VALUE_STRING: - sv = apfl_string_view_from(*value.string); + case VALUE_CONST_STRING: + sv = as_string_view(value); return apfl_hash_fnv1a_add(sv.bytes, sv.len, hash); case VALUE_LIST: for (size_t i = 0; i < value.list->len; i++) { @@ -490,6 +503,7 @@ apfl_value_get_gc_object(struct apfl_value value) case VALUE_NIL: case VALUE_BOOLEAN: case VALUE_NUMBER: + case VALUE_CONST_STRING: return NULL; case VALUE_STRING: return GC_OBJECT_FROM(value.string, GC_TYPE_STRING); diff --git a/src/value.h b/src/value.h index 1effec0..789bc55 100644 --- a/src/value.h +++ b/src/value.h @@ -20,6 +20,7 @@ enum value_type { VALUE_BOOLEAN, VALUE_NUMBER, VALUE_STRING, + VALUE_CONST_STRING, VALUE_LIST, VALUE_DICT, // TODO: functions/closures @@ -45,6 +46,7 @@ struct apfl_value { bool boolean; apfl_number number; struct apfl_string *string; + struct apfl_string_view const_string; struct list_header *list; struct dict_header *dict; };