2024-03-26 18:31:33 +00:00
|
|
|
#include "value.h"
|
2024-03-27 10:49:10 +00:00
|
|
|
#include "node.h"
|
2024-03-30 10:20:16 +00:00
|
|
|
#include "moka.h"
|
2024-03-26 18:31:33 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-27 10:49:10 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-29 20:11:46 +00:00
|
|
|
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; i<new_values->size; i++)
|
|
|
|
{
|
|
|
|
array_push_value(self->data.array, (MOKA) new_values->data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
self->type = TY_ARRAY;
|
|
|
|
self->line = line;
|
|
|
|
}
|
|
|
|
|
2024-03-30 10:20:16 +00:00
|
|
|
size_t value_str(struct value* self,
|
|
|
|
char* buffer,
|
|
|
|
size_t size,
|
|
|
|
struct moka* moka)
|
2024-03-29 20:11:46 +00:00
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(buffer);
|
2024-03-30 10:20:16 +00:00
|
|
|
|
2024-03-29 20:11:46 +00:00
|
|
|
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: {
|
2024-03-30 10:20:16 +00:00
|
|
|
return snprintf(buffer, size, "%s",
|
2024-03-29 20:11:46 +00:00
|
|
|
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, "<ref:%zu>", self->data.ref);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case TY_NATIVE: {
|
|
|
|
return snprintf(buffer, size, "<native: %p>", self->data.native);
|
|
|
|
} break;
|
2024-03-30 10:20:16 +00:00
|
|
|
|
2024-03-29 20:11:46 +00:00
|
|
|
case TY_LAZY: {
|
2024-03-30 10:20:16 +00:00
|
|
|
return snprintf(buffer, size, "<lazy:%s>",
|
2024-03-29 20:11:46 +00:00
|
|
|
NodeKindStr[self->data.lazy->kind]
|
|
|
|
+ strlen("NODE_"));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case TY_ARRAY: {
|
|
|
|
size_t sz = 0;
|
2024-03-30 10:20:16 +00:00
|
|
|
sz += snprintf(buffer + sz, size - sz, "[");
|
|
|
|
for (size_t i=0; i<self->data.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, "]");
|
2024-03-29 20:11:46 +00:00
|
|
|
return sz;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
fprintf(stderr, "cannot stringify value <%s>\n",
|
|
|
|
TypeKindStr[self->type]);
|
|
|
|
abort();
|
|
|
|
} break;
|
|
|
|
}
|
2024-03-30 10:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2024-03-29 20:11:46 +00:00
|
|
|
|
2024-03-30 10:20:16 +00:00
|
|
|
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; i<self->data.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;
|
|
|
|
}
|
2024-03-29 20:11:46 +00:00
|
|
|
}
|
|
|
|
|
2024-03-26 18:31:33 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2024-03-27 10:49:10 +00:00
|
|
|
if (self->type == TY_NATIVE)
|
|
|
|
{
|
|
|
|
native_free(self->data.native);
|
|
|
|
free(self->data.native);
|
|
|
|
}
|
2024-03-29 20:11:46 +00:00
|
|
|
|
|
|
|
if (self->type == TY_ARRAY)
|
|
|
|
{
|
|
|
|
array_free(self->data.array);
|
|
|
|
free(self->data.array);
|
|
|
|
}
|
2024-03-26 18:31:33 +00:00
|
|
|
}
|
2024-03-30 10:20:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
|