| 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; | ||||
| } | } |