| union { | union { | ||||
| l2_word ns_parent; | l2_word ns_parent; | ||||
| l2_word cont_call; | l2_word cont_call; | ||||
| l2_word buf_length; | |||||
| l2_word arr_length; | |||||
| } extra; | } extra; | ||||
| // Byte 4: 1 byte, 3 bytes padding | // Byte 4: 1 byte, 3 bytes padding | ||||
| union { | union { | ||||
| l2_word atom; | l2_word atom; | ||||
| double real; | double real; | ||||
| struct l2_vm_buffer *buffer; | |||||
| char *buffer; | |||||
| struct l2_vm_array *array; | struct l2_vm_array *array; | ||||
| struct l2_vm_namespace *ns; | struct l2_vm_namespace *ns; | ||||
| struct { | struct { | ||||
| #define l2_vm_value_type(val) ((enum l2_value_type)((val)->flags & 0x0f)) | #define l2_vm_value_type(val) ((enum l2_value_type)((val)->flags & 0x0f)) | ||||
| struct l2_vm_buffer { | |||||
| size_t len; | |||||
| char data[]; | |||||
| }; | |||||
| struct l2_vm_array { | struct l2_vm_array { | ||||
| size_t len; | |||||
| size_t size; | size_t size; | ||||
| l2_word data[]; | l2_word data[]; | ||||
| }; | }; |
| case L2_VAL_TYPE_BUFFER: | case L2_VAL_TYPE_BUFFER: | ||||
| if (val->buffer != NULL) { | if (val->buffer != NULL) { | ||||
| out->write(out, val->buffer->data, val->buffer->len); | |||||
| out->write(out, val->buffer, val->extra.buf_length); | |||||
| } | } | ||||
| break; | break; | ||||
| case L2_VAL_TYPE_ARRAY: | case L2_VAL_TYPE_ARRAY: | ||||
| if (val->array == NULL) { | |||||
| out->write(out, "[]", 2); | |||||
| break; | |||||
| } | |||||
| out->write(out, "[", 1); | out->write(out, "[", 1); | ||||
| for (size_t i = 0; i < val->array->len; ++i) { | |||||
| for (size_t i = 0; i < val->extra.arr_length; ++i) { | |||||
| if (i != 0) { | if (i != 0) { | ||||
| out->write(out, " ", 1); | out->write(out, " ", 1); | ||||
| } | } | ||||
| return vm->kfalse; | return vm->kfalse; | ||||
| } | } | ||||
| if (a->buffer->len != b->buffer->len) { | |||||
| if (a->extra.buf_length != b->extra.buf_length) { | |||||
| return vm->kfalse; | return vm->kfalse; | ||||
| } | } | ||||
| if (memcmp(a->buffer->data, b->buffer->data, a->buffer->len) != 0) { | |||||
| if (memcmp(a->buffer, b->buffer, a->extra.buf_length) != 0) { | |||||
| return vm->kfalse; | return vm->kfalse; | ||||
| } | } | ||||
| } else { | } else { | ||||
| break; | break; | ||||
| case L2_VAL_TYPE_BUFFER: | case L2_VAL_TYPE_BUFFER: | ||||
| if (val->buffer) { | |||||
| ret->real = val->buffer->len; | |||||
| } | |||||
| ret->real = val->extra.buf_length; | |||||
| break; | break; | ||||
| case L2_VAL_TYPE_ARRAY: | case L2_VAL_TYPE_ARRAY: | ||||
| if (val->array) { | |||||
| ret->real = val->array->len; | |||||
| } | |||||
| ret->real = val->extra.arr_length; | |||||
| break; | break; | ||||
| case L2_VAL_TYPE_NAMESPACE: | case L2_VAL_TYPE_NAMESPACE: |
| return; | return; | ||||
| } | } | ||||
| printf("ARRAY, len %zu\n", val->array->len); | |||||
| for (size_t i = 0; i < val->array->len; ++i) { | |||||
| printf("ARRAY, len %u\n", val->extra.arr_length); | |||||
| for (size_t i = 0; i < val->extra.arr_length; ++i) { | |||||
| printf(" %zu: %u\n", i, val->array->data[i]); | printf(" %zu: %u\n", i, val->array->data[i]); | ||||
| } | } | ||||
| } | } | ||||
| return; | return; | ||||
| } | } | ||||
| printf("BUFFER, len %zu\n", val->buffer->len); | |||||
| for (size_t i = 0; i < val->buffer->len; ++i) { | |||||
| printf(" %zu: %c\n", i, val->buffer->data[i]); | |||||
| printf("BUFFER, len %u\n", val->extra.buf_length); | |||||
| for (size_t i = 0; i < val->extra.buf_length; ++i) { | |||||
| printf(" %zu: %c\n", i, val->buffer[i]); | |||||
| } | } | ||||
| } | } | ||||
| break; | break; |
| return; | return; | ||||
| } | } | ||||
| for (size_t i = 0; i < val->array->len; ++i) { | |||||
| for (size_t i = 0; i < val->extra.arr_length; ++i) { | |||||
| gc_mark(vm, val->array->data[i]); | gc_mark(vm, val->array->data[i]); | ||||
| } | } | ||||
| } | } | ||||
| vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; | vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; | ||||
| vm->values[arr_id].array = malloc( | vm->values[arr_id].array = malloc( | ||||
| sizeof(struct l2_vm_array) + sizeof(l2_word) * argc); | sizeof(struct l2_vm_array) + sizeof(l2_word) * argc); | ||||
| vm->values[arr_id].extra.arr_length = argc; | |||||
| struct l2_vm_array *arr = vm->values[arr_id].array; | struct l2_vm_array *arr = vm->values[arr_id].array; | ||||
| arr->len = argc; | |||||
| arr->size = argc; | arr->size = argc; | ||||
| for (l2_word i = 0; i < argc; ++i) { | for (l2_word i = 0; i < argc; ++i) { | ||||
| l2_word length = read(vm); \ | l2_word length = read(vm); \ | ||||
| l2_word offset = read(vm); \ | l2_word offset = read(vm); \ | ||||
| vm->values[word].flags = L2_VAL_TYPE_BUFFER; \ | vm->values[word].flags = L2_VAL_TYPE_BUFFER; \ | ||||
| vm->values[word].buffer = malloc(sizeof(struct l2_vm_buffer) + length); \ | |||||
| vm->values[word].buffer->len = length; \ | |||||
| memcpy( \ | |||||
| (unsigned char *)vm->values[word].buffer + sizeof(struct l2_vm_buffer), \ | |||||
| vm->ops + offset, length); \ | |||||
| vm->values[word].buffer = length > 0 ? malloc(length) : NULL; \ | |||||
| vm->values[word].extra.buf_length = length; \ | |||||
| memcpy(vm->values[word].buffer, vm->ops + offset, length); \ | |||||
| vm->stack[vm->sptr] = word; \ | vm->stack[vm->sptr] = word; \ | ||||
| vm->sptr += 1; | vm->sptr += 1; | ||||
| case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break; | case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break; | ||||
| l2_word arr_id = alloc_val(vm); \ | l2_word arr_id = alloc_val(vm); \ | ||||
| struct l2_vm_value *arr = &vm->values[arr_id]; \ | struct l2_vm_value *arr = &vm->values[arr_id]; \ | ||||
| arr->flags = L2_VAL_TYPE_ARRAY; \ | arr->flags = L2_VAL_TYPE_ARRAY; \ | ||||
| arr->extra.arr_length = count; \ | |||||
| if (count == 0) { \ | if (count == 0) { \ | ||||
| arr->array = NULL; \ | arr->array = NULL; \ | ||||
| vm->stack[vm->sptr++] = arr_id; \ | vm->stack[vm->sptr++] = arr_id; \ | ||||
| break; \ | break; \ | ||||
| } \ | } \ | ||||
| arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \ | arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \ | ||||
| arr->array->len = count; \ | |||||
| arr->array->size = count; \ | arr->array->size = count; \ | ||||
| for (l2_word i = 0; i < count; ++i) { \ | for (l2_word i = 0; i < count; ++i) { \ | ||||
| arr->array->data[count - 1 - i] = vm->stack[--vm->sptr]; \ | arr->array->data[count - 1 - i] = vm->stack[--vm->sptr]; \ |