#include "value.h" void value_init_num(value_t* self, double num, int line) { assert(self); self->data.num = num; self->type = TYPE_NUM; self->line = line; } void value_init_new_tuple(value_t* self, vec_t* values, int line) { assert(self); assert(values); self->data.tuple = values; self->type = TYPE_TUPLE; self->line = line; } void value_init_boolean(value_t* self, int boolean, int line) { assert(self); self->data.boolean = boolean; self->type = TYPE_BOOLEAN; self->line = line; } void value_init_str(value_t* self, char const* value, int line) { assert(self); self->data.str = strdup(value); self->type = TYPE_STR; self->line = line; } void value_init_new_array(value_t* self, vec_t* value, int line) { assert(self); assert(value); self->data.array = value; self->type = TYPE_ARRAY; self->line = line; } void value_init_ref(value_t* self, size_t value, int line) { assert(self); self->data.ref = value; self->type = TYPE_REF; self->line = line; } value_t* value_new_clone(value_t* self) { assert(self); value_t* value = malloc(sizeof(value_t)); switch (self->type) { case TYPE_REF: { value_init_ref(value, self->data.ref, self->line); } break; case TYPE_ARRAY: { vec_t* array = malloc(sizeof(vec_t)); vec_init(array); for (size_t i=0; idata.array->size; i++) { vec_push(array, self->data.array->data[i] ); } value_init_new_array(value, array, self->line); } break; case TYPE_STR: { value_init_str(value, self->data.str, self->line); } break; case TYPE_NUM: { value_init_num(value, self->data.num, self->line); } break; case TYPE_BOOLEAN: { value_init_boolean(value, self->data.boolean, self->line); } break; case TYPE_TUPLE: { vec_t* vec = malloc(sizeof(vec_t)); vec_init(vec); for (size_t i=0; idata.tuple->size; i++) { vec_push( vec, value_new_clone(self->data.tuple->data[i]) ); } value_init_new_tuple(value, vec, self->line); } break; default: { free(value); fprintf(stderr, "cannot clone value of type '%s'\n", TypeStr[self->type]); abort(); } break; } return value; } void value_free(value_t* self) { if (self->type == TYPE_ARRAY) { vec_free(self->data.array); free(self->data.array); } if (self->type == TYPE_TUPLE) { vec_free_elements(self->data.tuple, (void*) value_free); vec_free(self->data.tuple); free(self->data.tuple); } if (self->type == TYPE_STR && self->data.str) { free(self->data.str); } } size_t value_str(value_t* self, char* buffer, size_t size) { assert(self); assert(buffer); size_t sz = 0; switch (self->type) { case TYPE_ARRAY: { sz += snprintf(buffer + sz, size - sz, "["); for (size_t i=0; idata.array->size; i++) { if (i > 0) { sz += snprintf(buffer + sz, size - sz, ", "); } sz += value_str( self->data.array->data[i], buffer + sz, size - sz ); } sz += snprintf(buffer + sz, size - sz, "]"); } break; case TYPE_REF: { sz += snprintf(buffer + sz, size - sz, "", self->data.ref); } break; case TYPE_STR: { sz += snprintf(buffer + sz, size - sz, "%s", self->data.str); } break; case TYPE_NUM: { sz += snprintf(buffer + sz, size - sz, "%lf", self->data.num); } break; case TYPE_BOOLEAN: { sz += snprintf(buffer + sz, size - sz, "%s", self->data.boolean ? "true" : "false"); } break; case TYPE_TUPLE: { sz += snprintf(buffer + sz, size - sz, "("); for (size_t i=0; i < self->data.tuple->size; i++) { if (i > 0) { sz += snprintf(buffer + sz, size - sz, ", "); } sz += value_str(self->data.tuple->data[i], buffer + sz, size - sz); } sz += snprintf(buffer + sz, size - sz, ")"); } break; default: assert(0); } return sz; } int value_equals(value_t* self, value_t* rhs) { assert(self); assert(rhs); if (self->type != rhs->type) { return 0; } switch (self->type) { case TYPE_ARRAY: { if (self->data.array->size != rhs->data.array->size) { return 0; } for (size_t i=0; idata.array->size; i++) { value_t* a = self->data.array->data[i]; value_t* b = rhs->data.array->data[i]; if (!value_equals(a, b)) { return 0; } } return 1; } break; case TYPE_REF: { return self->data.ref == rhs->data.ref; } break; case TYPE_STR: { return strcmp(self->data.str, rhs->data.str) == 0; } break; case TYPE_NUM: { return self->data.num == rhs->data.num; } break; case TYPE_BOOLEAN: { return self->data.boolean == rhs->data.boolean; } break; case TYPE_TUPLE: { if (self->data.tuple->size != rhs->data.tuple->size) { return 0; } for (size_t i=0; idata.tuple->size; i++) { if (!value_equals( self->data.tuple->data[i], rhs->data.tuple->data[i] )) { return 0; } } return 1; } break; default: { fprintf( stderr, "cannot test equality on value of type '%s'\n", TypeStr[self->type]); abort(); } break; } }