#include "value.h" #include "node.h" #include "moka.h" MK_ENUM_C(TypeKind, TYPE_KIND); void value_init_int(struct value* self, int value, int line) { assert(self); self->data.integer = value; self->type = TY_INT; self->line = line; } void value_init_float(struct value* self, float value, int line) { assert(self); self->data.real = value; self->type = TY_FLOAT; self->line = line; } void value_init_bool(struct value* self, bool value, int line) { assert(self); self->data.boolean = value; self->type = TY_BOOL; self->line = line; } void value_init_string(struct value* self, char const* value, int line) { assert(self); assert(value); self->data.str = strdup(value); self->type = TY_STRING; self->line = line; } void value_init_symbol(struct value* self, char const* value, int line) { assert(self); assert(value); self->data.sym = strdup(value); self->type = TY_SYMBOL; self->line = line; } void value_init_ref(struct value* self, size_t value, int line) { assert(self); self->data.ref = value; self->type = TY_REF; self->line = line; } void value_init_native(struct value* self, struct native* value, int line) { assert(self); assert(value); self->data.native = value; self->type = TY_NATIVE; self->line = line; } void value_init_lazy(struct value* self, struct node* value, int line) { assert(self); assert(value); self->data.lazy = value; self->type = TY_LAZY; self->line = line; } void value_init_array(struct value* self, struct vec* new_values, int line) { assert(self); assert(new_values); self->data.array = malloc(sizeof(struct array)); array_init(self->data.array); for (size_t i=0; isize; i++) { array_push_value(self->data.array, (MOKA) new_values->data[i]); } self->type = TY_ARRAY; self->line = line; } size_t value_str(struct value* self, char* buffer, size_t size, struct moka* moka) { assert(self); assert(buffer); switch (self->type) { case TY_INT: { return snprintf(buffer, size, "%d", self->data.integer); } break; case TY_FLOAT: { return snprintf(buffer, size, "%f", self->data.real); } break; case TY_BOOL: { return snprintf(buffer, size, "%s", self->data.boolean ? "true" : "false"); } break; case TY_STRING: { return snprintf(buffer, size, "%s", self->data.str); } break; case TY_SYMBOL: { return snprintf(buffer, size, "%s", self->data.sym); } break; case TY_REF: { return snprintf(buffer, size, "", self->data.ref); } break; case TY_NATIVE: { return snprintf(buffer, size, "", self->data.native); } break; case TY_LAZY: { return snprintf(buffer, size, "", NodeKindStr[self->data.lazy->kind] + strlen("NODE_")); } break; case TY_ARRAY: { size_t sz = 0; sz += snprintf(buffer + sz, size - sz, "["); for (size_t i=0; idata.array->values.size; i++) { if (i > 0) { sz += snprintf(buffer + sz, size - sz, " "); } MOKA val = (MOKA) self->data.array->values.data[i]; sz += moka_str(moka, val, buffer + sz, size - sz); } sz += snprintf(buffer + sz, size - sz, "]"); return sz; } break; default: { fprintf(stderr, "cannot stringify value <%s>\n", TypeKindStr[self->type]); abort(); } break; } } bool value_is_eqv(struct value* self, struct value* rhs, struct moka* moka) { if (self->type != rhs->type) { return false; } switch (self->type) { case TY_INT: { return self->data.integer == rhs->data.integer; } break; case TY_FLOAT: { return self->data.real == rhs->data.real; } break; case TY_BOOL: { return self->data.boolean == rhs->data.boolean; } break; case TY_STRING: { return strcmp(self->data.str, rhs->data.str) == 0; } break; case TY_SYMBOL: { return strcmp(self->data.sym, rhs->data.sym) == 0; } break; case TY_REF: { return self->data.ref == rhs->data.ref; } break; case TY_ARRAY: { if (self->data.array->values.size != rhs->data.array->values.size) { return false; } for (size_t i=0; idata.array->values.size; i++) { MOKA first = (MOKA) self->data.array->values.data[i]; MOKA second = (MOKA) rhs->data.array->values.data[i]; if (!moka_is_eqv(moka, first, second)) { return false; } } return true; } break; case TY_NATIVE: { return false; } break; case TY_LAZY: { return true; } break; default: { fprintf(stderr, "cannot test eqv on type <%s>\n", TypeKindStr[self->type]); abort(); } break; } } void value_free(struct value* self) { assert(self); if (self->type == TY_STRING) { free(self->data.str); } if (self->type == TY_SYMBOL) { free(self->data.sym); } if (self->type == TY_NATIVE) { native_free(self->data.native); free(self->data.native); } if (self->type == TY_ARRAY) { array_free(self->data.array); free(self->data.array); } }