#include "moka.h" #include "node.h" #include "compiler.h" #include "prog.h" #include "exec.h" void moka_init(struct moka* self, struct status* status) { assert(self); self->status = status; symtable_init(&self->symtable); 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); symtable_free(&self->symtable); vec_free_elements(&self->frame_stack, (void*) frame_free); vec_free(&self->frame_stack); vec_free_elements(&self->global_values, (void*) value_free); vec_free(&self->global_values); } void moka_decl_native(struct moka* self, char* name, native_fun_t fun) { struct native* native = malloc(sizeof(struct native)); native_init(native, fun); struct value* value = malloc(sizeof(struct value)); value_init_native(value, native, 0); vec_push(&self->global_values, value); size_t addr = self->global_values.size - 1; symtable_declare(&self->symtable, name, addr, false); } 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; } MOKA moka_pop(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]; vec_pop(&frame->stack); 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_REF)) { printf("&%zu", moka_get_ref(self, value)); return; } 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_call(struct moka* self, int arg_count) { MOKA fun = moka_pop(self); struct vec args; vec_init(&args); for (ssize_t i=0; iglobal_values.data[ moka_get_ref(self, fun) ]; assert(val->type == TY_NATIVE); struct native* native = val->data.native; (native->fun)(self, &args); vec_free(&args); return moka_top(self); } 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; } MOKA moka_push_ref(struct moka* self, size_t value, int line) { assert(self); struct frame* frame = moka_frame(self); struct value* val = malloc(sizeof(struct value)); value_init_ref(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; } size_t moka_get_ref(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_REF); return val->data.ref; } MOKA moka_push_native(struct moka* self, native_fun_t value, int line) { assert(self); assert(value); struct native* native = malloc(sizeof(struct native)); native_init(native, value); struct value* val = malloc(sizeof(struct value)); value_init_native(val, native, line); vec_push(&self->global_values, val); size_t addr = self->global_values.size - 1; return moka_push_ref(self, addr, line); } native_fun_t moka_get_native(struct moka* self, MOKA value) { assert(self); size_t addr = moka_get_ref(self, value); struct value const* val = self->global_values.data[addr]; struct native const* native = val->data.native; return native->fun; } MOKA moka_eval_lazy(struct moka* self, MOKA lazy_value) { assert(self); if (!moka_is(self, lazy_value, TY_LAZY)) { return lazy_value; } struct node* node = moka_get_lazy(self, lazy_value); struct compiler compiler; compiler_init(&compiler, self->status); struct prog prog; prog_init(&prog); compiler_compile( &compiler, node, &prog, &self->symtable); if (!status_is_ok(self->status)) { status_dump(self->status); moka_push_int(self, 0, 0); goto free_prog; } struct exec exec; exec_init(&exec); exec_prog(&exec, self, &prog); exec_free(&exec); free_prog: prog_free(&prog); compiler_free(&compiler); return moka_pop(self); } MOKA moka_push_lazy(struct moka* self, struct node* value, int line) { assert(self); assert(value); struct value* val = malloc(sizeof(struct value)); value_init_lazy(val, value, line); struct frame* frame = moka_frame(self); vec_push(&frame->local_values, val); size_t addr = frame->local_values.size - 1; vec_push(&frame->stack, (void*) addr); return addr; } struct node* moka_get_lazy(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_LAZY); return val->data.lazy; }