91961bcec5
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
138 lines
3.1 KiB
C
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;
|
|
}
|
|
|