80 lines
1.6 KiB
C

#pragma once
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
#include "vmstring.h"
#include "vmstate.h"
enum vm_type {
VT_CONS,
VT_STRING,
VT_FUNC,
};
struct vm_value {
enum vm_type type;
size_t refcount;
union {
struct {
uintptr_t fat_ar, fat_dr;
} v_cons;
struct {
size_t lib_index, fn_index;
} v_func;
struct vm_string v_string;
};
};
static inline int ref_q(uint64_t w) {
return (w & FLAG_REF) != 0;
}
static inline int null_q(uint64_t w) {
return w == FLAG_REF;
}
static inline struct vm_value *getref(uint64_t w) {
assert(ref_q(w));
return (struct vm_value *) (w << 1);
}
static inline int cons_q(uint64_t w) {
if (ref_q(w)) {
return null_q(w) || getref(w)->type == VT_CONS;
} else {
return 0;
}
}
static inline int func_q(uint64_t w) {
return ref_q(w) && !null_q(w) && getref(w)->type == VT_FUNC;
}
static inline int pair_q(uint64_t w) {
return ref_q(w) && (!null_q(w) && getref(w)->type == VT_CONS);
}
void vm_value_ref(struct vm_value *v);
int vm_value_unref(struct vm_value *v);
static inline void vm_ref(uint64_t w) {
if (ref_q(w)) {
vm_value_ref(getref(w));
}
}
static inline int vm_unref(uint64_t w) {
if (ref_q(w)) {
return vm_value_unref(getref(w));
}
return 0;
}
void vm_value_free(struct vm_value *val);
struct vm_value *vm_cons(uint64_t w0, uint64_t w1);
struct vm_value *vm_makestr(const char *str);
struct vm_value *vm_func(size_t lib_index, size_t fn_index);
void vm_print(uint64_t w);