217 lines
5.3 KiB
C
217 lines
5.3 KiB
C
#include "moka.h"
|
|
|
|
void moka_init(struct moka* self)
|
|
{
|
|
assert(self);
|
|
vec_init(&self->frame_stack);
|
|
vec_init(&self->global_values);
|
|
|
|
struct frame* frame = malloc(sizeof(struct frame));
|
|
frame_init(frame);
|
|
vec_push(&self->frame_stack, frame);
|
|
}
|
|
|
|
void frame_init(struct frame* self)
|
|
{
|
|
vec_init(&self->local_values);
|
|
vec_init(&self->stack);
|
|
}
|
|
|
|
void frame_free(struct frame* self)
|
|
{
|
|
assert(self);
|
|
vec_free_elements(&self->local_values, (void*)value_free);
|
|
vec_free(&self->local_values);
|
|
vec_free(&self->stack);
|
|
}
|
|
|
|
void moka_free(struct moka* self)
|
|
{
|
|
assert(self);
|
|
vec_free_elements(&self->frame_stack, (void*) frame_free);
|
|
vec_free(&self->frame_stack);
|
|
vec_free(&self->global_values);
|
|
}
|
|
|
|
struct frame* moka_frame(struct moka* self)
|
|
{
|
|
assert(self);
|
|
assert(self->frame_stack.size > 0);
|
|
return self->frame_stack.data[
|
|
self->frame_stack.size - 1
|
|
];
|
|
}
|
|
|
|
bool moka_has_top(struct moka* self)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
return frame->stack.size > 0;
|
|
}
|
|
|
|
MOKA moka_top(struct moka* self)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
assert(frame->stack.size > 0);
|
|
MOKA val = (MOKA) frame->stack.data[frame->stack.size - 1];
|
|
return val;
|
|
}
|
|
|
|
bool moka_is(struct moka* self, MOKA value, TypeKind type)
|
|
{
|
|
return moka_type_of(self, value) == type;
|
|
}
|
|
|
|
TypeKind moka_type_of(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value const* val = frame->local_values.data[value];
|
|
return val->type;
|
|
}
|
|
|
|
void moka_dump(struct moka* self, MOKA value)
|
|
{
|
|
if (moka_is(self, value, TY_INT))
|
|
{
|
|
printf("%d", moka_get_int(self, value));
|
|
return;
|
|
}
|
|
|
|
if (moka_is(self, value, TY_FLOAT))
|
|
{
|
|
printf("%f", moka_get_float(self, value));
|
|
return;
|
|
}
|
|
|
|
if (moka_is(self, value, TY_BOOL))
|
|
{
|
|
printf("%s", moka_get_bool(self, value) ? "true" : "false");
|
|
return;
|
|
}
|
|
|
|
if (moka_is(self, value, TY_STRING))
|
|
{
|
|
printf("%s", moka_get_string(self, value));
|
|
return;
|
|
}
|
|
|
|
if (moka_is(self, value, TY_SYMBOL))
|
|
{
|
|
printf("'%s", moka_get_symbol(self, value));
|
|
return;
|
|
}
|
|
|
|
fprintf(stderr, "cannot dump value of type <%s>\n",
|
|
TypeKindStr[moka_type_of(self, value)]
|
|
);
|
|
|
|
abort();
|
|
}
|
|
|
|
MOKA moka_push_int(struct moka* self, int value, int line)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = malloc(sizeof(struct value));
|
|
value_init_int(val, value, line);
|
|
vec_push(&frame->local_values, val);
|
|
size_t addr = frame->local_values.size - 1;
|
|
vec_push(&frame->stack, (void*) addr);
|
|
return addr;
|
|
}
|
|
|
|
int moka_get_int(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = frame->local_values.data[value];
|
|
assert(val->type == TY_INT);
|
|
return val->data.integer;
|
|
}
|
|
|
|
MOKA moka_push_float(struct moka* self, float value, int line)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = malloc(sizeof(struct value));
|
|
value_init_float(val, value, line);
|
|
vec_push(&frame->local_values, val);
|
|
size_t addr = frame->local_values.size - 1;
|
|
vec_push(&frame->stack, (void*) addr);
|
|
return addr;
|
|
}
|
|
|
|
float moka_get_float(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = frame->local_values.data[value];
|
|
assert(val->type == TY_FLOAT);
|
|
return val->data.real;
|
|
}
|
|
|
|
MOKA moka_push_bool(struct moka* self, bool value, int line)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = malloc(sizeof(struct value));
|
|
value_init_bool(val, value, line);
|
|
vec_push(&frame->local_values, val);
|
|
size_t addr = frame->local_values.size - 1;
|
|
vec_push(&frame->stack, (void*) addr);
|
|
return addr;
|
|
}
|
|
|
|
float moka_get_bool(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = frame->local_values.data[value];
|
|
assert(val->type == TY_BOOL);
|
|
return val->data.boolean;
|
|
}
|
|
|
|
MOKA moka_push_string(struct moka* self, char const* value, int line)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = malloc(sizeof(struct value));
|
|
value_init_string(val, value, line);
|
|
vec_push(&frame->local_values, val);
|
|
size_t addr = frame->local_values.size - 1;
|
|
vec_push(&frame->stack, (void*) addr);
|
|
return addr;
|
|
}
|
|
|
|
char* moka_get_string(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = frame->local_values.data[value];
|
|
assert(val->type == TY_STRING);
|
|
return val->data.str;
|
|
}
|
|
|
|
MOKA moka_push_symbol(struct moka* self, char const* value, int line)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = malloc(sizeof(struct value));
|
|
value_init_symbol(val, value, line);
|
|
vec_push(&frame->local_values, val);
|
|
size_t addr = frame->local_values.size - 1;
|
|
vec_push(&frame->stack, (void*) addr);
|
|
return addr;
|
|
}
|
|
|
|
char* moka_get_symbol(struct moka* self, MOKA value)
|
|
{
|
|
assert(self);
|
|
struct frame* frame = moka_frame(self);
|
|
struct value* val = frame->local_values.data[value];
|
|
assert(val->type == TY_SYMBOL);
|
|
return val->data.sym;
|
|
}
|