2024-03-18 17:20:40 +00:00
|
|
|
#include "ccm.h"
|
|
|
|
|
|
|
|
void ccm_init(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
vec_init(&self->values);
|
|
|
|
vec_init(&self->stack);
|
|
|
|
err_init(&self->err);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_free(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
err_free(&self->err);
|
|
|
|
vec_free_elements(&self->values, (void*) value_free);
|
|
|
|
vec_free(&self->values);
|
|
|
|
vec_free(&self->stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t ccm_str(ccm_t* self, char* buffer, size_t size)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(buffer);
|
|
|
|
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
for (size_t i=0; i<self->stack.size; i++)
|
|
|
|
{
|
|
|
|
value_t* val = self->values.data[(CCM) self->stack.data[i]];
|
|
|
|
sz += value_str(val, buffer + sz, size - sz);
|
|
|
|
sz += snprintf(buffer + sz, size - sz, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_is_num(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
value_t const* val = self->values.data[value];
|
|
|
|
return val->type == TYPE_NUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ccm_from_num(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(value < self->values.size);
|
|
|
|
|
|
|
|
if (!ccm_is_num(self, value))
|
|
|
|
{
|
|
|
|
err_push(&self->err,
|
|
|
|
((value_t*) self->values.data[value])->line,
|
|
|
|
"not a num");
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t* val = self->values.data[value];
|
|
|
|
|
|
|
|
return val->data.num;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_num(ccm_t* self, double value, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t* val = malloc(sizeof(value_t));
|
|
|
|
value_init_num(val, value, line);
|
|
|
|
vec_push(&self->values, val);
|
|
|
|
|
|
|
|
return self->values.size - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_is_tuple(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t* val = self->values.data[value];
|
|
|
|
assert(val);
|
|
|
|
return val->type == TYPE_TUPLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec_t* ccm_from_tuple(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t* val = self->values.data[value];
|
|
|
|
if (!ccm_is_tuple(self, value))
|
|
|
|
{
|
|
|
|
err_push(&self->err, val->line, "not a tuple");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return val->data.tuple;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_tuple(ccm_t* self, vec_t* values, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(values);
|
|
|
|
value_t* value = malloc(sizeof(value_t));
|
|
|
|
value_init_new_tuple(value, values, line);
|
|
|
|
|
|
|
|
vec_push(&self->values, value);
|
|
|
|
return self->values.size - 1;
|
|
|
|
}
|
|
|
|
|
2024-03-19 06:11:28 +00:00
|
|
|
int ccm_is_boolean(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return ((value_t*) self->values.data[value])->type
|
|
|
|
== TYPE_BOOLEAN;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_from_boolean(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return ((value_t*) self->values.data[value])->data.boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_boolean(ccm_t* self, int value, int line)
|
|
|
|
{
|
|
|
|
value_t* boolean = malloc(sizeof(value_t));
|
|
|
|
value_init_boolean(boolean, value, line);
|
|
|
|
vec_push(&self->values, boolean);
|
|
|
|
return self->values.size - 1;
|
|
|
|
}
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
void ccm_push(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
vec_push(&self->stack, (void*) value);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_pop(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
void* val = vec_pop(&self->stack);
|
|
|
|
return (CCM) val;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_top(ccm_t* self, int depth)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert((size_t) depth < self->stack.size);
|
|
|
|
|
|
|
|
return (CCM) self->stack.data[self->stack.size - 1 - depth];
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_add(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, lhs + rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_sub(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, lhs - rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_usub(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, -lhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_mul(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, lhs * rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_div(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, lhs / rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_mod(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, fmod(lhs, rhs), line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_pow(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_num(self, powf(lhs, rhs), line));
|
|
|
|
}
|
2024-03-19 06:11:28 +00:00
|
|
|
|
|
|
|
void ccm_not(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
int line = ((value_t*) self->values.data[ccm_lhs])->line;
|
|
|
|
|
|
|
|
int lhs = ccm_from_boolean(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_boolean(self, !lhs, line));
|
|
|
|
}
|