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]; \ |