aboutsummaryrefslogtreecommitdiff
path: root/src/value.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/value.c')
-rw-r--r--src/value.c130
1 files changed, 130 insertions, 0 deletions
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 <string.h>
+#include <stdio.h>
+#ifdef DEBUG
+#define GC_DEBUG
+#endif
+#include <gc.h>
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;
+}