#include "vmstate.h" #include "vmval.h" #include "error.h" #include "load.h" #include "unit.h" #include #define ARG(name) \ uint64_t name; \ if ((res = vm_pop(vm, &name)) != 0) { \ return res; \ } #define ARG_INTEGER(name) \ int64_t name; \ if ((res = vm_pop_integer(vm, &name)) != 0) { \ return res; \ } // I/O stuff static int c_print(struct vm *vm) { int res; ARG(w); if (string_q(w)) { fputs(getref(w)->v_string.data, stdout); } else { vm_print(stdout, w); } vm_unref(w); return 0; } static int c_println(struct vm *vm) { int res; if ((res = c_print(vm)) != 0) { return res; } putc('\n', stdout); return 0; } static int c_putc(struct vm *vm) { int res; ARG_INTEGER(c); putc(c, stdout); return 0; } // String stuff static int c_string_length(struct vm *vm) { int res; ARG(w); if (!string_q(w)) { return -ERR_OPERAND_TYPE; } struct vm_value *v = getref(w); size_t len = vm_strlen(&v->v_string); vm_value_unref(v); return vm_push_integer(vm, len); } static int c_string_ref(struct vm *vm) { int res; ARG(s); ARG_INTEGER(i); if (!string_q(s)) { return -ERR_OPERAND_TYPE; } struct vm_value *v = getref(s); char c; if (i < 0 || (size_t) i >= vm_strlen(&v->v_string)) { vm_value_unref(v); return -ERR_RANGE; } c = v->v_string.data[i]; vm_value_unref(v); return vm_push_integer(vm, c); } static int c_extra_func(struct vm *vm) { int res; ARG(w); printf("Runtime-resolved function was called!\n"); vm_unref(w); return 0; } static int c_native(struct vm *vm) { int res; ARG(w); if (!string_q(w)) { return -ERR_OPERAND_TYPE; } struct vm_value *name = getref(w); struct vm_value *sym; if (!strcmp(name->v_string.data, "extra-func")) { sym = vm_cfunc((uintptr_t) c_extra_func); } else { return -ERR_SYMBOL_UNDEFINED; } vm_value_unref(name); vm_value_ref(sym); vm_push_ref(vm, sym); return 0; } static struct vm_export_entry c_unit_core_exports[] = { { 1, { (uintptr_t) c_println }, "println" }, { 1, { (uintptr_t) c_print }, "print" }, { 1, { (uintptr_t) c_putc }, "putc" }, //{ 1, { (uintptr_t) c_string_length }, "string-new" }, { 1, { (uintptr_t) c_string_length }, "string-length" }, { 1, { (uintptr_t) c_string_ref }, "string-ref" }, //{ 1, { (uintptr_t) c_string_length }, "string-ref" }, { 1, { (uintptr_t) c_native }, "native" }, }; int load_core(struct vm_unit_info *info) { struct vm_export_entry *ent; assert(info); vector_init(&info->exports, sizeof(struct vm_export_entry)); for (size_t i = 0; i < sizeof(c_unit_core_exports) / sizeof(struct vm_export_entry); ++i) { ent = vector_append(&info->exports); if (!ent) { return -ERR_OUT_OF_MEMORY; } memcpy(ent, &c_unit_core_exports[i], sizeof(struct vm_export_entry)); } info->unit = NULL; info->index = 0xFFFFFFFF; return 0; }