From 31519e8a586791d60e6e56e558c2a3bf973cc1f9 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 26 Jan 2020 08:02:17 +0100 Subject: Implement plus operator and indexing of strings --- src/value.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) (limited to 'src/value.c') diff --git a/src/value.c b/src/value.c index 1a76880..61d6d4a 100644 --- a/src/value.c +++ b/src/value.c @@ -1,5 +1,11 @@ #include "../include/value.h" +#include "../include/std_gc/hash_map.h" #include +#include +#ifdef DEBUG +#define GC_DEBUG +#endif +#include static uint64_t hash_range(const uint8_t *data, size_t size) { uint64_t result = 0xdec05eba; @@ -11,6 +17,11 @@ static uint64_t hash_range(const uint8_t *data, size_t size) { return result; } +static void tsl_string_to_ref(const TslString *self, TslStringView *result) { + result->data = self->data; + result->size = self->size; +} + uint64_t tsl_value_hash(const TslValue *key) { switch((TslType)key->type) { case TSL_TYPE_NULL: @@ -60,3 +71,122 @@ int tsl_value_equals(const TslValue *lhs, const TslValue *rhs) { void tsl_value_clear(TslValue *self) { memset(self, 0, sizeof(TslValue)); } + +static int tsl_string_merge(const TslStringView *str1, const TslStringView *str2, TslString **result) { + size_t new_size = str1->size + str2->size; + char *new_str_data; + *result = GC_MALLOC_ATOMIC(sizeof(TslString)); + new_str_data = GC_MALLOC_ATOMIC(new_size + 1); + + if(!*result) { + GC_FREE(*result); + GC_FREE(new_str_data); + fprintf(stderr, "Error: out of memory\n"); + return 0; + } + if(!new_str_data) { + GC_FREE(*result); + GC_FREE(new_str_data); + fprintf(stderr, "Error: out of memory\n"); + return 0; + } + + memcpy(new_str_data, str1->data, str1->size); + memcpy(new_str_data + str1->size, str2->data, str2->size); + new_str_data[new_size] = '\0'; + (*result)->data = new_str_data; + (*result)->size = new_size; + + return 1; +} + +int tsl_value_add(const TslValue *lhs_value, const TslValue *rhs_value, TslValue *result) { + tsl_value_clear(result); + switch((TslType)lhs_value->type) { + case TSL_TYPE_NULL: + case TSL_TYPE_BOOL: + case TSL_TYPE_MAP: + case TSL_TYPE_FUNCTION: + case TSL_TYPE_USERDATA: { + fprintf(stderr, "Error: Unable to perform operation '+' on a TODO\n"); + return 0; + } + case TSL_TYPE_NUMBER: { + if(rhs_value->type != TSL_TYPE_NUMBER) { + fprintf(stderr, "Error: Unable to perform operation '+' on a number and a TODO\n"); + return 0; + } + result->data.number = lhs_value->data.number + rhs_value->data.number; + result->type = TSL_TYPE_NUMBER; + return 1; + } + case TSL_TYPE_STRING: { + TslStringView lhs_str; + tsl_string_to_ref(lhs_value->data.string, &lhs_str); + result->type = TSL_TYPE_STRING; + if(rhs_value->type == TSL_TYPE_STRING) { + TslStringView rhs_str; + tsl_string_to_ref(rhs_value->data.string, &rhs_str); + return tsl_string_merge(&lhs_str, &rhs_str, &result->data.string); + } else if(rhs_value->type == TSL_TYPE_STRING_REF) { + return tsl_string_merge(&lhs_str, &rhs_value->data.string_ref, &result->data.string); + } else { + fprintf(stderr, "Error: Unable to perform operation '+' on a string and TODO\n"); + return 0; + } + result->type = TSL_TYPE_STRING; + return 1; + } + case TSL_TYPE_STRING_REF: { + result->type = TSL_TYPE_STRING; + if(rhs_value->type == TSL_TYPE_STRING) { + TslStringView rhs_str; + tsl_string_to_ref(rhs_value->data.string, &rhs_str); + return tsl_string_merge(&lhs_value->data.string_ref, &rhs_str, &result->data.string); + } else if(rhs_value->type == TSL_TYPE_STRING_REF) { + return tsl_string_merge(&lhs_value->data.string_ref, &rhs_value->data.string_ref, &result->data.string); + } else { + fprintf(stderr, "Error: Unable to perform operation '+' on a string and TODO\n"); + return 0; + } + result->type = TSL_TYPE_STRING; + return 1; + } + case TSL_TYPE_LIST: { + /* + Create a new list by combining lhs_value list and rhs_value list. + For example, [1, 2] + [3, 4] becomes [1, 2, 3, 4] + */ + size_t list_size = sizeof(TslValue) * (lhs_value->data.list->size + rhs_value->data.list->size); + + if(rhs_value->type != TSL_TYPE_LIST) { + fprintf(stderr, "Error: Unable to perform operation '+' on a list and a TODO\n"); + return 0; + } + + result->data.list = GC_MALLOC(sizeof(TslList)); + if(!result->data.list) { + fprintf(stderr, "Error: Failed to create list. Reason: out of memory\n"); + return 0; + } + + tsl_list_set_capacity_hint(result->data.list, list_size); + result->data.list->size = list_size; + + memcpy((char*)result->data.list->data, lhs_value->data.list->data, lhs_value->data.list->size); + memcpy((char*)result->data.list->data + lhs_value->data.list->size, rhs_value->data.list->data, rhs_value->data.list->size); + + result->type = TSL_TYPE_LIST; + return 1; + } + } + return 0; +} + +TslValue* tsl_string_ref_get(const TslStringView *self, double index) { + /* TODO: Verify if overflow check is needed */ + intptr_t index_i = index; + if(index_i >= 0 && index_i < (intptr_t)self->size / (intptr_t)sizeof(TslValue)) + return (TslValue*)self->data + index_i; + return NULL; +} -- cgit v1.2.3