137 lines
2.9 KiB
C
137 lines
2.9 KiB
C
#include "vmval.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
static void vm_print2(FILE *fp, uint64_t w, int cdepth);
|
|
|
|
static void vm_print_ref(FILE *fp, struct vm_value *value, int cdepth) {
|
|
uint64_t w0;
|
|
if (!value) {
|
|
fprintf(fp, "nil");
|
|
return;
|
|
}
|
|
switch (value->type) {
|
|
case VT_STRING:
|
|
fprintf(fp, "\"%s\"", vm_cstr(&value->v_string));
|
|
break;
|
|
case VT_CONS:
|
|
if (!cdepth) {
|
|
printf("(");
|
|
}
|
|
vm_print2(fp, value->v_cons.fat_ar, 0);
|
|
w0 = value->v_cons.fat_dr;
|
|
if (!null_q(w0)) {
|
|
fprintf(fp, " ");
|
|
if (cons_q(w0)) {
|
|
vm_print2(fp, w0, cdepth + 1);
|
|
} else {
|
|
fprintf(fp, ". ");
|
|
vm_print2(fp, w0, cdepth + 1);
|
|
}
|
|
}
|
|
if (!cdepth) {
|
|
fprintf(fp, ")");
|
|
}
|
|
break;
|
|
case VT_FUNC:
|
|
fprintf(fp, "<function %zu:%zu>", value->v_func.lib_index, value->v_func.fn_index);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void vm_print2(FILE *fp, uint64_t w, int cdepth) {
|
|
if (w & FLAG_REF) {
|
|
vm_print_ref(fp, (void *) (w << 1), cdepth);
|
|
} else {
|
|
if (w & (1ULL << 62)) {
|
|
w |= 1ULL << 63;
|
|
}
|
|
fprintf(fp, "%ld", (int64_t) w);
|
|
}
|
|
}
|
|
|
|
static struct vm_value *vm_value_create(enum vm_type type) {
|
|
struct vm_value *v = calloc(1, sizeof(struct vm_value));
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
v->type = type;
|
|
v->refcount = 0;
|
|
return v;
|
|
}
|
|
|
|
void vm_value_free(struct vm_value *v) {
|
|
if (!v) {
|
|
return;
|
|
}
|
|
assert(v->refcount == 0);
|
|
switch (v->type) {
|
|
case VT_CONS:
|
|
vm_unref(v->v_cons.fat_ar);
|
|
vm_unref(v->v_cons.fat_dr);
|
|
break;
|
|
case VT_STRING:
|
|
// TODO
|
|
default:
|
|
break;
|
|
}
|
|
free(v);
|
|
}
|
|
|
|
void vm_value_ref(struct vm_value *v) {
|
|
if (!v) {
|
|
return;
|
|
}
|
|
++v->refcount;
|
|
}
|
|
|
|
int vm_value_unref(struct vm_value *v) {
|
|
if (!v) {
|
|
return 0;
|
|
}
|
|
assert(v->refcount);
|
|
--v->refcount;
|
|
if (v->refcount == 0) {
|
|
vm_value_free(v);
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
struct vm_value *vm_cons(uint64_t w0, uint64_t w1) {
|
|
struct vm_value *v = vm_value_create(VT_CONS);
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
vm_ref(w0);
|
|
vm_ref(w1);
|
|
v->v_cons.fat_ar = w0;
|
|
v->v_cons.fat_dr = w1;
|
|
return v;
|
|
}
|
|
|
|
struct vm_value *vm_makestr(const char *str) {
|
|
struct vm_value *v = vm_value_create(VT_STRING);
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
vm_string_init(&v->v_string, str);
|
|
return v;
|
|
}
|
|
|
|
struct vm_value *vm_func(size_t lib_index, size_t fn_index) {
|
|
struct vm_value *v = vm_value_create(VT_FUNC);
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
v->v_func.lib_index = lib_index;
|
|
v->v_func.fn_index = fn_index;
|
|
return v;
|
|
}
|
|
|
|
void vm_print(FILE *fp, uint64_t w) {
|
|
vm_print2(fp, w, 0);
|
|
}
|