#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; istack.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; } 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)); }