101 lines
2.2 KiB
C
101 lines
2.2 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;
|
|
}
|
|
v->type = type;
|
|
v->refcount = 0;
|
|
return v;
|
|
}
|
|
|
|
void vm_value_free(struct vm_value *v) {
|
|
assert(v->refcount == 0);
|
|
free(v);
|
|
}
|
|
|
|
struct vm_value *vm_cons(uint64_t w0, uint64_t w1) {
|
|
struct vm_value *v = vm_value_create(VT_CONS);
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
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);
|
|
}
|