L2_OP_ALLOC_INTEGER_64, | L2_OP_ALLOC_INTEGER_64, | ||||
L2_OP_ALLOC_REAL_32, | L2_OP_ALLOC_REAL_32, | ||||
L2_OP_ALLOC_REAL_64, | L2_OP_ALLOC_REAL_64, | ||||
L2_OP_ALLOC_ARRAY, | |||||
L2_OP_ALLOC_BUFFER, | L2_OP_ALLOC_BUFFER, | ||||
L2_OP_ALLOC_BUFFER_CONST, | L2_OP_ALLOC_BUFFER_CONST, | ||||
L2_OP_ALLOC_ARRAY, | |||||
L2_OP_ALLOC_MAP, | |||||
L2_OP_HALT, | L2_OP_HALT, | ||||
}; | }; | ||||
L2_VAL_TYPE_NONE, | L2_VAL_TYPE_NONE, | ||||
L2_VAL_TYPE_INTEGER, | L2_VAL_TYPE_INTEGER, | ||||
L2_VAL_TYPE_REAL, | L2_VAL_TYPE_REAL, | ||||
L2_VAL_TYPE_ARRAY, | |||||
L2_VAL_TYPE_BUFFER, | L2_VAL_TYPE_BUFFER, | ||||
L2_VAL_TYPE_ARRAY, | |||||
L2_VAL_TYPE_MAP, | |||||
L2_VAL_MARKED = 1 << 7, | L2_VAL_MARKED = 1 << 7, | ||||
L2_VAL_CONST = 1 << 8, | L2_VAL_CONST = 1 << 8, | ||||
} flags; | } flags; | ||||
}; | }; | ||||
struct l2_vm_buffer { | struct l2_vm_buffer { | ||||
struct l2_vm_value val; | |||||
size_t len; | size_t len; | ||||
char data[]; | |||||
}; | }; | ||||
struct l2_vm_array { | struct l2_vm_array { | ||||
struct l2_vm_value val; | |||||
size_t len; | size_t len; | ||||
size_t size; | size_t size; | ||||
l2_word data[]; | |||||
}; | |||||
struct l2_vm_map { | |||||
size_t len; | |||||
size_t size; | |||||
l2_word data[]; | |||||
}; | }; | ||||
struct l2_vm { | struct l2_vm { | ||||
}; | }; | ||||
void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount); | void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount); | ||||
void l2_vm_free(struct l2_vm *vm); | |||||
void l2_vm_step(struct l2_vm *vm); | void l2_vm_step(struct l2_vm *vm); | ||||
void l2_vm_run(struct l2_vm *vm); | void l2_vm_run(struct l2_vm *vm); | ||||
size_t l2_vm_gc(struct l2_vm *vm); | size_t l2_vm_gc(struct l2_vm *vm); |
case L2_VAL_TYPE_ARRAY: | case L2_VAL_TYPE_ARRAY: | ||||
{ | { | ||||
struct l2_vm_array *arr = (struct l2_vm_array *)val->data; | struct l2_vm_array *arr = (struct l2_vm_array *)val->data; | ||||
l2_word *data = (l2_word *)((char *)arr + sizeof(struct l2_vm_array)); | |||||
printf("ARRAY, len %zu\n", arr->len); | printf("ARRAY, len %zu\n", arr->len); | ||||
for (size_t i = 0; i < arr->len; ++i) { | for (size_t i = 0; i < arr->len; ++i) { | ||||
printf(" %zu: %u\n", i, data[i]); | |||||
printf(" %zu: %u\n", i, arr->data[i]); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case L2_VAL_TYPE_BUFFER: | case L2_VAL_TYPE_BUFFER: | ||||
{ | { | ||||
struct l2_vm_buffer *buf = (struct l2_vm_buffer *)val->data; | struct l2_vm_buffer *buf = (struct l2_vm_buffer *)val->data; | ||||
char *data = (char *)buf + sizeof(struct l2_vm_buffer); | |||||
printf("BUFFER, len %zu\n", buf->len); | printf("BUFFER, len %zu\n", buf->len); | ||||
for (size_t i = 0; i < buf->len; ++i) { | for (size_t i = 0; i < buf->len; ++i) { | ||||
printf(" %zu: %c\n", i, data[i]); | |||||
printf(" %zu: %c\n", i, buf->data[i]); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
print_var(&vm.values[i]); | print_var(&vm.values[i]); | ||||
} | } | ||||
} | } | ||||
l2_vm_free(&vm); | |||||
} | } |
int typ = val->flags & 0x0f; | int typ = val->flags & 0x0f; | ||||
if (typ == L2_VAL_TYPE_ARRAY) { | if (typ == L2_VAL_TYPE_ARRAY) { | ||||
struct l2_vm_array *arr = (struct l2_vm_array *)val->data; | struct l2_vm_array *arr = (struct l2_vm_array *)val->data; | ||||
l2_word *ids = (l2_word *)((char *)arr + sizeof(struct l2_vm_array)); | |||||
for (size_t i = 0; i < arr->len; ++i) { | for (size_t i = 0; i < arr->len; ++i) { | ||||
gc_mark(vm, ids[i]); | |||||
gc_mark(vm, arr->data[i]); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
vm->values[none_id].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST; | vm->values[none_id].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST; | ||||
} | } | ||||
void l2_vm_free(struct l2_vm *vm) { | |||||
// Skip ID 0, because that should always exist | |||||
for (size_t i = 1; i < vm->valuessize; ++i) { | |||||
if (!l2_bitset_get(&vm->valueset, i)) { | |||||
continue; | |||||
} | |||||
gc_free(vm, i); | |||||
} | |||||
free(vm->values); | |||||
l2_bitset_free(&vm->valueset); | |||||
} | |||||
size_t l2_vm_gc(struct l2_vm *vm) { | size_t l2_vm_gc(struct l2_vm *vm) { | ||||
for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) { | for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) { | ||||
if (vm->stackflags[sptr]) { | if (vm->stackflags[sptr]) { | ||||
vm->sptr += 1; | vm->sptr += 1; | ||||
break; | break; | ||||
case L2_OP_ALLOC_ARRAY: | |||||
word = alloc_val(vm); | |||||
vm->values[word].flags = L2_VAL_TYPE_ARRAY; | |||||
vm->values[word].data = calloc(1, sizeof(struct l2_vm_array)); | |||||
vm->stack[vm->sptr] = word; | |||||
vm->stackflags[vm->sptr] = 1; | |||||
vm->sptr += 1; | |||||
break; | |||||
case L2_OP_ALLOC_BUFFER: | case L2_OP_ALLOC_BUFFER: | ||||
word = alloc_val(vm); | word = alloc_val(vm); | ||||
vm->values[word].flags = L2_VAL_TYPE_BUFFER; | vm->values[word].flags = L2_VAL_TYPE_BUFFER; | ||||
} | } | ||||
break; | break; | ||||
case L2_OP_ALLOC_ARRAY: | |||||
word = alloc_val(vm); | |||||
vm->values[word].flags = L2_VAL_TYPE_ARRAY; | |||||
vm->values[word].data = calloc(1, sizeof(struct l2_vm_array)); | |||||
vm->stack[vm->sptr] = word; | |||||
vm->stackflags[vm->sptr] = 1; | |||||
vm->sptr += 1; | |||||
break; | |||||
case L2_OP_ALLOC_MAP: | |||||
word = alloc_val(vm); | |||||
vm->values[word].flags = L2_VAL_TYPE_MAP; | |||||
vm->values[word].data = calloc(1, sizeof(struct l2_vm_map)); | |||||
vm->stack[vm->sptr] = word; | |||||
vm->stackflags[vm->sptr] = 1; | |||||
vm->sptr += 1; | |||||
break; | |||||
case L2_OP_HALT: | case L2_OP_HALT: | ||||
break; | break; | ||||
} | } |