147 lines
3.0 KiB
C
147 lines
3.0 KiB
C
#include "vmval.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
static void vm_print2(uint64_t w, int cdepth);
|
|
|
|
static void vm_print_ref(struct vm_value *value, int cdepth) {
|
|
uint64_t w0;
|
|
if (!value) {
|
|
printf("nil");
|
|
return;
|
|
}
|
|
switch (value->type) {
|
|
case VT_STRING:
|
|
printf("\"%s\"", vm_cstr(&value->v_string));
|
|
break;
|
|
case VT_CONS:
|
|
if (!cdepth) {
|
|
printf("(");
|
|
}
|
|
vm_print2(value->v_cons.fat_ar, 0);
|
|
w0 = value->v_cons.fat_dr;
|
|
if (!null_q(w0)) {
|
|
printf(" ");
|
|
if (cons_q(w0)) {
|
|
vm_print2(w0, cdepth + 1);
|
|
} else {
|
|
printf(". ");
|
|
vm_print2(w0, cdepth + 1);
|
|
}
|
|
}
|
|
if (!cdepth) {
|
|
printf(")");
|
|
}
|
|
break;
|
|
case VT_FUNC:
|
|
printf("<function %zu:%zu>", value->v_func.lib_index, value->v_func.fn_index);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void vm_print2(uint64_t w, int cdepth) {
|
|
if (w & FLAG_REF) {
|
|
vm_print_ref((void *) (w << 1), cdepth);
|
|
} else {
|
|
if (w & (1ULL << 62)) {
|
|
w |= 1ULL << 63;
|
|
}
|
|
printf("%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;
|
|
}
|
|
printf("create %p\n", v);
|
|
v->type = type;
|
|
v->refcount = 0;
|
|
return v;
|
|
}
|
|
|
|
void vm_value_free(struct vm_value *v) {
|
|
if (!v) {
|
|
return;
|
|
}
|
|
printf("free %p: ", v);
|
|
vm_print_ref(v, 0);
|
|
printf("\n");
|
|
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;
|
|
}
|
|
printf("ref %p: ", v);
|
|
vm_print_ref(v, 0);
|
|
printf("\n");
|
|
++v->refcount;
|
|
}
|
|
|
|
int vm_value_unref(struct vm_value *v) {
|
|
if (!v) {
|
|
return 0;
|
|
}
|
|
printf("unref %p: ", v);
|
|
vm_print_ref(v, 0);
|
|
printf("\n");
|
|
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(uint64_t w) {
|
|
vm_print2(w, 0);
|
|
}
|