thesis-lisp/vm/vmval.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);
}