Files
alnyan 91961bcec5 Lots of changes with long commit message again
1. (list ...)
2. string-* functions
3. (native str) to resolve native functions at runtime
4. Memory fuckups in compiler core unit loading
5. Now can call non-identifiers in compiler
2021-04-09 00:18:48 +03:00

138 lines
3.1 KiB
C

#include "vmstate.h"
#include "vmval.h"
#include "error.h"
#include "load.h"
#include "unit.h"
#include <string.h>
#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;
}