149 lines
3.2 KiB
C
149 lines
3.2 KiB
C
|
#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;
|
||
|
}
|
||
|
|
||
|
value_t* value_new_clone(value_t* self)
|
||
|
{
|
||
|
assert(self);
|
||
|
|
||
|
value_t* value = malloc(sizeof(value_t));
|
||
|
|
||
|
switch (self->type)
|
||
|
{
|
||
|
case TYPE_NUM: {
|
||
|
value_init_num(value, self->data.num, self->line);
|
||
|
} break;
|
||
|
case TYPE_TUPLE: {
|
||
|
vec_t* vec = malloc(sizeof(vec_t));
|
||
|
vec_init(vec);
|
||
|
|
||
|
for (size_t i=0; i<self->data.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_TUPLE)
|
||
|
{
|
||
|
vec_free_elements(self->data.tuple, (void*) value_free);
|
||
|
vec_free(self->data.tuple);
|
||
|
free(self->data.tuple);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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_NUM: {
|
||
|
sz += snprintf(buffer + sz, size - sz, "%lf",
|
||
|
self->data.num);
|
||
|
} 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_NUM: {
|
||
|
return self->data.num == rhs->data.num;
|
||
|
} break;
|
||
|
|
||
|
case TYPE_TUPLE: {
|
||
|
if (self->data.tuple->size != rhs->data.tuple->size)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for (size_t i=0; i<self->data.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;
|
||
|
}
|
||
|
}
|