2024-03-18 17:20:40 +00:00
|
|
|
#include "ccm.h"
|
2024-03-19 13:23:11 +00:00
|
|
|
#include "str.h"
|
2024-03-18 17:20:40 +00:00
|
|
|
|
|
|
|
void ccm_init(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-21 11:00:20 +00:00
|
|
|
sym_init(&self->sym);
|
2024-03-18 17:20:40 +00:00
|
|
|
vec_init(&self->values);
|
|
|
|
vec_init(&self->stack);
|
2024-03-20 15:26:59 +00:00
|
|
|
vec_init(&self->globals);
|
2024-03-18 17:20:40 +00:00
|
|
|
err_init(&self->err);
|
2024-03-20 15:26:59 +00:00
|
|
|
self->id_counter = 0;
|
2024-03-21 11:00:20 +00:00
|
|
|
|
|
|
|
sym_open_scope(&self->sym);
|
2024-03-20 15:26:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_entry_free(ccm_entry_t* self)
|
|
|
|
{
|
|
|
|
value_free(self->value);
|
|
|
|
free(self->value);
|
2024-03-18 17:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_free(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-21 11:00:20 +00:00
|
|
|
sym_free(&self->sym);
|
2024-03-18 17:20:40 +00:00
|
|
|
err_free(&self->err);
|
2024-03-20 15:26:59 +00:00
|
|
|
vec_free_elements(&self->values, (void*) ccm_entry_free);
|
2024-03-18 17:20:40 +00:00
|
|
|
vec_free(&self->values);
|
|
|
|
vec_free(&self->stack);
|
2024-03-20 15:26:59 +00:00
|
|
|
vec_free(&self->globals);
|
2024-03-18 17:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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++)
|
|
|
|
{
|
2024-03-22 22:01:20 +00:00
|
|
|
if (sz >= size)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = ccm_to_value(self, (CCM) self->stack.data[i]);
|
2024-03-18 17:20:40 +00:00
|
|
|
sz += value_str(val, buffer + sz, size - sz);
|
|
|
|
sz += snprintf(buffer + sz, size - sz, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* ccm_find_value(ccm_t* self, size_t addr)
|
|
|
|
{
|
|
|
|
for (size_t i=0; i<self->values.size; i++)
|
|
|
|
{
|
|
|
|
if (((ccm_entry_t*) self->values.data[i])->id == (int) addr)
|
|
|
|
{
|
|
|
|
return ((ccm_entry_t*)self->values.data[i])->value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t ccm_add_value(ccm_t* self, value_t* value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(value);
|
|
|
|
|
|
|
|
ccm_entry_t* entry = malloc(sizeof(ccm_entry_t));
|
|
|
|
entry->value = value;
|
|
|
|
entry->id = self->id_counter;
|
|
|
|
self->id_counter++;
|
|
|
|
|
|
|
|
vec_push(&self->values, entry);
|
|
|
|
return self->id_counter - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t ccm_store_global(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
|
|
|
|
vec_push(&self->globals, (void*) value);
|
|
|
|
return self->globals.size - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_load_global(ccm_t* self, size_t addr)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(addr < self->globals.size);
|
|
|
|
|
|
|
|
return (CCM) self->globals.data[addr];
|
|
|
|
}
|
|
|
|
|
2024-03-19 07:56:41 +00:00
|
|
|
CCM ccm_from_value(ccm_t* self, value_t* value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(value);
|
|
|
|
|
|
|
|
switch (value->type)
|
|
|
|
{
|
|
|
|
case TYPE_NUM: {
|
|
|
|
return ccm_to_num(self, value->data.num, value->line);
|
|
|
|
} break;
|
|
|
|
|
2024-03-19 13:23:11 +00:00
|
|
|
case TYPE_STR: {
|
|
|
|
return ccm_to_str(self, value->data.str, value->line);
|
|
|
|
} break;
|
|
|
|
|
2024-03-19 07:56:41 +00:00
|
|
|
case TYPE_BOOLEAN: {
|
|
|
|
return ccm_to_boolean(
|
2024-03-19 13:23:11 +00:00
|
|
|
self,
|
|
|
|
value->data.boolean,
|
2024-03-19 07:56:41 +00:00
|
|
|
value->line
|
|
|
|
);
|
|
|
|
} break;
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
case TYPE_ARRAY: {
|
|
|
|
vec_t * vec = malloc(sizeof(vec_t));
|
|
|
|
vec_init(vec);
|
|
|
|
for (size_t i=0; i<value->data.array->size; i++)
|
|
|
|
{
|
|
|
|
vec_push(vec,
|
|
|
|
value->data.array->data[i]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ccm_to_array(
|
|
|
|
self,
|
|
|
|
vec,
|
|
|
|
value->line
|
|
|
|
);
|
|
|
|
} break;
|
2024-03-19 07:56:41 +00:00
|
|
|
case TYPE_TUPLE: {
|
|
|
|
vec_t * vec = malloc(sizeof(vec_t));
|
|
|
|
vec_init(vec);
|
|
|
|
for (size_t i=0; i<value->data.tuple->size; i++)
|
|
|
|
{
|
|
|
|
vec_push(vec, value_new_clone(
|
|
|
|
value->data.tuple->data[i]
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ccm_to_tuple(
|
2024-03-19 13:23:11 +00:00
|
|
|
self,
|
|
|
|
vec,
|
2024-03-19 07:56:41 +00:00
|
|
|
value->line
|
|
|
|
);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: {
|
2024-03-19 13:23:11 +00:00
|
|
|
fprintf(stderr,
|
2024-03-19 07:56:41 +00:00
|
|
|
"cannot convert value of type <%s> to CCM\n",
|
|
|
|
TypeStr[value->type]);
|
|
|
|
abort();
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-19 15:25:02 +00:00
|
|
|
value_t* ccm_to_value(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = ccm_find_value(self, value);
|
|
|
|
|
|
|
|
if (val->type == TYPE_REF)
|
|
|
|
{
|
|
|
|
CCM addr = (CCM) self->globals.data[val->data.ref];
|
|
|
|
return ccm_to_value(self, addr);
|
|
|
|
}
|
|
|
|
return val;
|
2024-03-19 15:25:02 +00:00
|
|
|
}
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
int ccm_is_num(ccm_t* self, CCM value)
|
|
|
|
{
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t const* val = ccm_find_value(self, value);
|
2024-03-18 17:20:40 +00:00
|
|
|
return val->type == TYPE_NUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ccm_from_num(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(value < self->values.size);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = ccm_find_value(self, value);
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
if (!ccm_is_num(self, value))
|
|
|
|
{
|
2024-03-20 15:26:59 +00:00
|
|
|
err_push(&self->err, val->line, "not a num");
|
2024-03-18 17:20:40 +00:00
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_add_value(self, val);
|
2024-03-18 17:20:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_is_tuple(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = ccm_find_value(self, value);
|
2024-03-18 17:20:40 +00:00
|
|
|
assert(val);
|
|
|
|
return val->type == TYPE_TUPLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec_t* ccm_from_tuple(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = ccm_find_value(self, value);
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
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);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_add_value(self, value);
|
2024-03-18 17:20:40 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 06:11:28 +00:00
|
|
|
int ccm_is_boolean(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_find_value(self, value)->type == TYPE_BOOLEAN;
|
2024-03-19 06:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_from_boolean(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_find_value(self, value)->data.boolean;
|
2024-03-19 06:11:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_boolean(ccm_t* self, int value, int line)
|
|
|
|
{
|
|
|
|
value_t* boolean = malloc(sizeof(value_t));
|
|
|
|
value_init_boolean(boolean, value, line);
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_add_value(self, boolean);
|
2024-03-19 06:11:28 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 13:23:11 +00:00
|
|
|
int ccm_is_str(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_find_value(self, value)->type == TYPE_STR;
|
2024-03-19 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char* ccm_from_str(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_find_value(self, value)->data.str;
|
2024-03-19 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_str(ccm_t* self, char* value, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(value);
|
|
|
|
|
|
|
|
value_t* val = malloc(sizeof(value_t));
|
|
|
|
value_init_str(val, value, line);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
return ccm_add_value(self, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_is_array(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t const* val = ccm_find_value(self, value);
|
|
|
|
return val->type == TYPE_ARRAY;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec_t* ccm_from_array(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t* val = ccm_find_value(self, value);
|
|
|
|
return val->data.array;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_array(ccm_t* self, vec_t* value, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
value_t* val = malloc(sizeof(value_t));
|
|
|
|
value_init_new_array(val, value, line);
|
|
|
|
return ccm_add_value(self, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ccm_is_ref(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return ccm_find_value(self, value)->type == TYPE_REF;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t ccm_from_ref(ccm_t* self, CCM value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return ccm_find_value(self, value)->data.ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_to_ref(ccm_t* self, size_t value, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
2024-03-19 13:23:11 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
value_t* val = malloc(sizeof(value_t));
|
|
|
|
value_init_ref(val, value, line);
|
|
|
|
return ccm_add_value(self, val);
|
2024-03-19 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2024-03-21 11:00:20 +00:00
|
|
|
void ccm_set(ccm_t* self, CCM value, int addr)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
while (addr >= (ssize_t) self->stack.size)
|
|
|
|
{
|
|
|
|
ccm_push(self, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
self->stack.data[addr] = (void*) value;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCM ccm_get(ccm_t* self, int addr)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(addr < (ssize_t) self->stack.size);
|
|
|
|
assert(addr >= 0);
|
|
|
|
|
|
|
|
return (CCM) self->stack.data[addr];
|
|
|
|
}
|
|
|
|
|
2024-03-19 07:56:41 +00:00
|
|
|
void ccm_in(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
2024-03-19 13:23:11 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 07:56:41 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
if (ccm_is_ref(self, ccm_rhs)) {
|
|
|
|
value_t* rhs_val = ccm_to_value(self, ccm_rhs);
|
|
|
|
value_t* val = ccm_to_value(self, ccm_lhs);
|
|
|
|
assert(rhs_val->type == TYPE_ARRAY);
|
|
|
|
vec_t* rhs = rhs_val->data.array;
|
2024-03-19 07:56:41 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
for (size_t i=0; i<rhs->size; i++)
|
|
|
|
{
|
|
|
|
if (value_equals(val, rhs->data[i]))
|
|
|
|
{
|
|
|
|
ccm_push(self, ccm_to_boolean(self, 1, line));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 13:23:11 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
ccm_push(self, ccm_to_boolean(self, 0, line));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (ccm_is_tuple(self, ccm_rhs)) {
|
|
|
|
vec_t* rhs = ccm_from_tuple(self, ccm_rhs);
|
|
|
|
value_t* val = ccm_find_value(self, ccm_lhs);
|
2024-03-19 07:56:41 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
for (size_t i=0; i<rhs->size; i++)
|
2024-03-19 07:56:41 +00:00
|
|
|
{
|
2024-03-20 15:26:59 +00:00
|
|
|
if (value_equals(val, rhs->data[i]))
|
|
|
|
{
|
|
|
|
ccm_push(self, ccm_to_boolean(self, 1, line));
|
|
|
|
return;
|
|
|
|
}
|
2024-03-19 07:56:41 +00:00
|
|
|
}
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
ccm_push(self, ccm_to_boolean(self, 0, line));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
err_push(&self->err, line, "cannot test membership");
|
|
|
|
return;
|
2024-03-19 07:56:41 +00:00
|
|
|
}
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
void ccm_add(ccm_t* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
|
|
|
|
|
|
|
if (ccm_is_ref(self, ccm_rhs)
|
|
|
|
&& ccm_is_ref(self, ccm_lhs))
|
|
|
|
{
|
|
|
|
value_t* lhs = ccm_to_value(self, ccm_lhs);
|
|
|
|
value_t* rhs = ccm_to_value(self, ccm_rhs);
|
|
|
|
|
|
|
|
vec_t* data = malloc(sizeof(vec_t));
|
|
|
|
vec_init(data);
|
|
|
|
|
|
|
|
for (size_t i=0; i<lhs->data.array->size; i++)
|
|
|
|
{
|
|
|
|
vec_push(data,
|
|
|
|
lhs->data.array->data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i=0; i<rhs->data.array->size; i++)
|
|
|
|
{
|
|
|
|
vec_push(data,
|
|
|
|
rhs->data.array->data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t* res = malloc(sizeof(value_t));
|
|
|
|
value_init_new_array(res, data, lhs->line);
|
2024-03-18 17:20:40 +00:00
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
CCM res_id = ccm_store_global(
|
|
|
|
self,
|
|
|
|
ccm_add_value(self, res)
|
|
|
|
);
|
|
|
|
|
|
|
|
value_t* ref = malloc(sizeof(value_t));
|
|
|
|
value_init_ref(ref, res_id, lhs->line);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_add_value(self, ref));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2024-03-19 13:23:11 +00:00
|
|
|
if (ccm_is_str(self, ccm_rhs)
|
|
|
|
&& ccm_is_str(self, ccm_lhs))
|
|
|
|
{
|
|
|
|
char const* lhs = ccm_from_str(self, ccm_lhs);
|
|
|
|
char const* rhs = ccm_from_str(self, ccm_rhs);
|
|
|
|
|
|
|
|
str_t s;
|
|
|
|
str_init(&s);
|
|
|
|
str_push_cstr(&s, lhs);
|
|
|
|
str_push_cstr(&s, rhs);
|
|
|
|
ccm_push(self, ccm_to_str(self, s.value, line));
|
|
|
|
str_free(&s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
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);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-18 17:20:40 +00:00
|
|
|
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);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-18 17:20:40 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
|
|
|
|
|
|
|
if (ccm_is_ref(self, ccm_rhs)
|
|
|
|
&& ccm_is_num(self, ccm_lhs))
|
|
|
|
{
|
|
|
|
CCM tmp = ccm_lhs;
|
|
|
|
ccm_lhs = ccm_rhs;
|
|
|
|
ccm_rhs = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ccm_is_ref(self, ccm_lhs)
|
|
|
|
&& ccm_is_num(self, ccm_rhs))
|
|
|
|
{
|
|
|
|
int count = ccm_from_num(self, ccm_rhs);
|
|
|
|
value_t* val = ccm_to_value(self, ccm_lhs);
|
|
|
|
vec_t* vec = malloc(sizeof(vec_t));
|
|
|
|
vec_init(vec);
|
|
|
|
|
|
|
|
for (int i=0; i<count; i++)
|
|
|
|
{
|
|
|
|
for (size_t j=0; j<val->data.array->size; j++)
|
|
|
|
{
|
|
|
|
vec_push(
|
|
|
|
vec,
|
|
|
|
val->data.array->data[j]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t* result = malloc(sizeof(value_t));
|
|
|
|
value_init_new_array(result, vec, val->line);
|
|
|
|
|
|
|
|
int id = ccm_store_global(
|
|
|
|
self,
|
|
|
|
ccm_add_value(self, result)
|
|
|
|
);
|
|
|
|
CCM res = ccm_to_ref(self, id, val->line);
|
|
|
|
ccm_push(self, res);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2024-03-19 13:23:11 +00:00
|
|
|
if (ccm_is_str(self, ccm_rhs)
|
|
|
|
&& ccm_is_num(self, ccm_lhs))
|
|
|
|
{
|
|
|
|
CCM tmp = ccm_lhs;
|
|
|
|
ccm_lhs = ccm_rhs;
|
|
|
|
ccm_rhs = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ccm_is_str(self, ccm_lhs)
|
|
|
|
&& ccm_is_num(self, ccm_rhs))
|
|
|
|
{
|
|
|
|
int count = ccm_from_num(self, ccm_rhs);
|
|
|
|
char const* val = ccm_from_str(self, ccm_lhs);
|
|
|
|
str_t s;
|
|
|
|
str_init(&s);
|
|
|
|
|
|
|
|
for (int i=0; i<count; i++)
|
|
|
|
{
|
|
|
|
str_push_cstr(&s, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_str(self, s.value, line));
|
|
|
|
str_free(&s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-18 17:20:40 +00:00
|
|
|
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);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-18 17:20:40 +00:00
|
|
|
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);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-18 17:20:40 +00:00
|
|
|
|
|
|
|
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);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-18 17:20:40 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 06:11:28 +00:00
|
|
|
int lhs = ccm_from_boolean(self, ccm_lhs);
|
|
|
|
|
|
|
|
ccm_push(self, ccm_to_boolean(self, !lhs, line));
|
|
|
|
}
|
2024-03-19 15:25:02 +00:00
|
|
|
|
|
|
|
void ccm_eq(ccm_t* self)
|
|
|
|
{
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
value_t* lhs = ccm_to_value(self, ccm_lhs);
|
|
|
|
value_t* rhs = ccm_to_value(self, ccm_rhs);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 15:25:02 +00:00
|
|
|
int eq = value_equals(lhs, rhs);
|
|
|
|
ccm_push(self, ccm_to_boolean(self, eq, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_ne(ccm_t* self)
|
|
|
|
{
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
|
|
|
|
value_t* lhs = ccm_to_value(self, ccm_lhs);
|
|
|
|
value_t* rhs = ccm_to_value(self, ccm_rhs);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 15:25:02 +00:00
|
|
|
int eq = value_equals(lhs, rhs);
|
|
|
|
ccm_push(self, ccm_to_boolean(self, !eq, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_lt(ccm_t* self)
|
|
|
|
{
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
|
|
|
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 15:25:02 +00:00
|
|
|
ccm_push(self, ccm_to_boolean(self, lhs < rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_le(ccm_t* self)
|
|
|
|
{
|
|
|
|
ccm_gt(self);
|
|
|
|
ccm_not(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_gt(ccm_t* self)
|
|
|
|
{
|
|
|
|
CCM ccm_rhs = ccm_pop(self);
|
|
|
|
CCM ccm_lhs = ccm_pop(self);
|
|
|
|
|
|
|
|
double lhs = ccm_from_num(self, ccm_lhs);
|
|
|
|
double rhs = ccm_from_num(self, ccm_rhs);
|
2024-03-20 15:26:59 +00:00
|
|
|
int line = ccm_find_value(self, ccm_lhs)->line;
|
2024-03-19 15:25:02 +00:00
|
|
|
ccm_push(self, ccm_to_boolean(self, lhs > rhs, line));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ccm_ge(ccm_t* self)
|
|
|
|
{
|
|
|
|
ccm_lt(self);
|
|
|
|
ccm_not(self);
|
|
|
|
}
|