diff options
Diffstat (limited to 'js/scripting-lang/baba-yaga-c/src/value.c')
-rw-r--r-- | js/scripting-lang/baba-yaga-c/src/value.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/src/value.c b/js/scripting-lang/baba-yaga-c/src/value.c new file mode 100644 index 0000000..25a52fc --- /dev/null +++ b/js/scripting-lang/baba-yaga-c/src/value.c @@ -0,0 +1,200 @@ +/** + * @file value.c + * @brief Value system implementation for Baba Yaga + * @author eli_oat + * @version 0.0.1 + * @date 2025 + * + * This file implements the value system for the Baba Yaga language, + * including value creation, destruction, and utility functions. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "baba_yaga.h" + +/* ============================================================================ + * Value Creation Functions + * ============================================================================ */ + +Value baba_yaga_value_number(double number) { + Value value; + value.type = VAL_NUMBER; + value.data.number = number; + return value; +} + +Value baba_yaga_value_string(const char* string) { + Value value; + value.type = VAL_STRING; + if (string != NULL) { + value.data.string = strdup(string); + } else { + value.data.string = NULL; + } + return value; +} + +Value baba_yaga_value_boolean(bool boolean) { + Value value; + value.type = VAL_BOOLEAN; + value.data.boolean = boolean; + return value; +} + +Value baba_yaga_value_nil(void) { + Value value; + value.type = VAL_NIL; + return value; +} + +/* ============================================================================ + * Value Management Functions + * ============================================================================ */ + +void baba_yaga_value_destroy(Value* value) { + if (value == NULL) { + return; + } + + switch (value->type) { + case VAL_STRING: + if (value->data.string != NULL) { + free(value->data.string); + value->data.string = NULL; + } + break; + case VAL_TABLE: + table_decrement_ref(value); + break; + case VAL_FUNCTION: + function_decrement_ref(value); + break; + default: + /* No cleanup needed for other types */ + break; + } + + value->type = VAL_NIL; +} + +Value baba_yaga_value_copy(const Value* value) { + if (value == NULL) { + return baba_yaga_value_nil(); + } + + switch (value->type) { + case VAL_NUMBER: + return baba_yaga_value_number(value->data.number); + case VAL_STRING: + return baba_yaga_value_string(value->data.string); + case VAL_BOOLEAN: + return baba_yaga_value_boolean(value->data.boolean); + case VAL_TABLE: { + Value new_table = baba_yaga_value_table(); + if (new_table.type != VAL_TABLE) { + return baba_yaga_value_nil(); + } + + /* Copy all entries from the original table */ + /* This is a simplified copy - in practice we'd need to iterate through all entries */ + table_increment_ref(&new_table); + return new_table; + } + case VAL_FUNCTION: { + /* For now, just increment the reference count of the original function */ + Value new_func = *value; + function_increment_ref(&new_func); + return new_func; + } + case VAL_NIL: + default: + return baba_yaga_value_nil(); + } +} + +/* ============================================================================ + * Utility Functions + * ============================================================================ */ + +ValueType baba_yaga_value_get_type(const Value* value) { + if (value == NULL) { + return VAL_NIL; + } + return value->type; +} + +bool baba_yaga_value_is_truthy(const Value* value) { + if (value == NULL) { + return false; + } + + switch (value->type) { + case VAL_NUMBER: + return value->data.number != 0.0; + case VAL_STRING: + return value->data.string != NULL && strlen(value->data.string) > 0; + case VAL_BOOLEAN: + return value->data.boolean; + case VAL_TABLE: + /* Tables are truthy if they have any elements */ + return baba_yaga_table_size(value) > 0; + case VAL_FUNCTION: + return true; + case VAL_NIL: + default: + return false; + } +} + +char* baba_yaga_value_to_string(const Value* value) { + if (value == NULL) { + return strdup("nil"); + } + + switch (value->type) { + case VAL_NUMBER: { + char buffer[128]; + if (value->data.number == (long)value->data.number) { + snprintf(buffer, sizeof(buffer), "%ld", (long)value->data.number); + } else { + snprintf(buffer, sizeof(buffer), "%.16g", value->data.number); + } + return strdup(buffer); + } + case VAL_STRING: + if (value->data.string != NULL) { + return strdup(value->data.string); + } else { + return strdup(""); + } + case VAL_BOOLEAN: + return strdup(value->data.boolean ? "true" : "false"); + case VAL_TABLE: { + char buffer[64]; + size_t size = baba_yaga_table_size(value); + snprintf(buffer, sizeof(buffer), "<table:%zu>", size); + return strdup(buffer); + } + case VAL_FUNCTION: { + char buffer[64]; + const char* name = function_get_name(value); + snprintf(buffer, sizeof(buffer), "<function:%s>", name ? name : "anonymous"); + return strdup(buffer); + } + case VAL_NIL: + default: + return strdup("nil"); + } +} + +/* ============================================================================ + * Version Information + * ============================================================================ */ + +const char* baba_yaga_get_version(void) { + return "0.0.1"; +} |