| @@ -49,6 +49,8 @@ struct l2_vm_value { | |||
| union { | |||
| l2_word ns_parent; | |||
| l2_word cont_call; | |||
| l2_word buf_length; | |||
| l2_word arr_length; | |||
| } extra; | |||
| // Byte 4: 1 byte, 3 bytes padding | |||
| @@ -58,7 +60,7 @@ struct l2_vm_value { | |||
| union { | |||
| l2_word atom; | |||
| double real; | |||
| struct l2_vm_buffer *buffer; | |||
| char *buffer; | |||
| struct l2_vm_array *array; | |||
| struct l2_vm_namespace *ns; | |||
| struct { | |||
| @@ -73,13 +75,7 @@ struct l2_vm_value { | |||
| #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 { | |||
| size_t len; | |||
| size_t size; | |||
| l2_word data[]; | |||
| }; | |||
| @@ -24,18 +24,13 @@ static void print_val(struct l2_vm *vm, struct l2_io_writer *out, struct l2_vm_v | |||
| case L2_VAL_TYPE_BUFFER: | |||
| if (val->buffer != NULL) { | |||
| out->write(out, val->buffer->data, val->buffer->len); | |||
| out->write(out, val->buffer, val->extra.buf_length); | |||
| } | |||
| break; | |||
| case L2_VAL_TYPE_ARRAY: | |||
| if (val->array == NULL) { | |||
| out->write(out, "[]", 2); | |||
| break; | |||
| } | |||
| 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) { | |||
| out->write(out, " ", 1); | |||
| } | |||
| @@ -200,11 +195,11 @@ l2_word l2_builtin_eq(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
| return vm->kfalse; | |||
| } | |||
| if (a->buffer->len != b->buffer->len) { | |||
| if (a->extra.buf_length != b->extra.buf_length) { | |||
| 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; | |||
| } | |||
| } else { | |||
| @@ -288,15 +283,11 @@ l2_word l2_builtin_len(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
| break; | |||
| case L2_VAL_TYPE_BUFFER: | |||
| if (val->buffer) { | |||
| ret->real = val->buffer->len; | |||
| } | |||
| ret->real = val->extra.buf_length; | |||
| break; | |||
| case L2_VAL_TYPE_ARRAY: | |||
| if (val->array) { | |||
| ret->real = val->array->len; | |||
| } | |||
| ret->real = val->extra.arr_length; | |||
| break; | |||
| case L2_VAL_TYPE_NAMESPACE: | |||
| @@ -58,8 +58,8 @@ void l2_vm_print_val(struct l2_vm_value *val) { | |||
| 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]); | |||
| } | |||
| } | |||
| @@ -72,9 +72,9 @@ void l2_vm_print_val(struct l2_vm_value *val) { | |||
| 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; | |||
| @@ -61,7 +61,7 @@ static void gc_mark_array(struct l2_vm *vm, struct l2_vm_value *val) { | |||
| 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]); | |||
| } | |||
| } | |||
| @@ -360,8 +360,8 @@ static void call_func( | |||
| vm->values[arr_id].flags = L2_VAL_TYPE_ARRAY; | |||
| vm->values[arr_id].array = malloc( | |||
| 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; | |||
| arr->len = argc; | |||
| arr->size = argc; | |||
| for (l2_word i = 0; i < argc; ++i) { | |||
| @@ -564,11 +564,9 @@ void l2_vm_step(struct l2_vm *vm) { | |||
| l2_word length = read(vm); \ | |||
| l2_word offset = read(vm); \ | |||
| 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->sptr += 1; | |||
| case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break; | |||
| @@ -580,13 +578,13 @@ void l2_vm_step(struct l2_vm *vm) { | |||
| l2_word arr_id = alloc_val(vm); \ | |||
| struct l2_vm_value *arr = &vm->values[arr_id]; \ | |||
| arr->flags = L2_VAL_TYPE_ARRAY; \ | |||
| arr->extra.arr_length = count; \ | |||
| if (count == 0) { \ | |||
| arr->array = NULL; \ | |||
| vm->stack[vm->sptr++] = arr_id; \ | |||
| break; \ | |||
| } \ | |||
| arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \ | |||
| arr->array->len = count; \ | |||
| arr->array->size = count; \ | |||
| for (l2_word i = 0; i < count; ++i) { \ | |||
| arr->array->data[count - 1 - i] = vm->stack[--vm->sptr]; \ | |||