@@ -18,9 +18,10 @@ enum l2_opcode { | |||
L2_OP_ALLOC_INTEGER_64, | |||
L2_OP_ALLOC_REAL_32, | |||
L2_OP_ALLOC_REAL_64, | |||
L2_OP_ALLOC_ARRAY, | |||
L2_OP_ALLOC_BUFFER, | |||
L2_OP_ALLOC_BUFFER_CONST, | |||
L2_OP_ALLOC_ARRAY, | |||
L2_OP_ALLOC_MAP, | |||
L2_OP_HALT, | |||
}; | |||
@@ -11,8 +11,9 @@ struct l2_vm_value { | |||
L2_VAL_TYPE_NONE, | |||
L2_VAL_TYPE_INTEGER, | |||
L2_VAL_TYPE_REAL, | |||
L2_VAL_TYPE_ARRAY, | |||
L2_VAL_TYPE_BUFFER, | |||
L2_VAL_TYPE_ARRAY, | |||
L2_VAL_TYPE_MAP, | |||
L2_VAL_MARKED = 1 << 7, | |||
L2_VAL_CONST = 1 << 8, | |||
} flags; | |||
@@ -24,14 +25,20 @@ struct l2_vm_value { | |||
}; | |||
struct l2_vm_buffer { | |||
struct l2_vm_value val; | |||
size_t len; | |||
char data[]; | |||
}; | |||
struct l2_vm_array { | |||
struct l2_vm_value val; | |||
size_t len; | |||
size_t size; | |||
l2_word data[]; | |||
}; | |||
struct l2_vm_map { | |||
size_t len; | |||
size_t size; | |||
l2_word data[]; | |||
}; | |||
struct l2_vm { | |||
@@ -49,6 +56,7 @@ struct l2_vm { | |||
}; | |||
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_run(struct l2_vm *vm); | |||
size_t l2_vm_gc(struct l2_vm *vm); |
@@ -21,10 +21,9 @@ void print_var(struct l2_vm_value *val) { | |||
case L2_VAL_TYPE_ARRAY: | |||
{ | |||
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); | |||
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; | |||
@@ -32,10 +31,9 @@ void print_var(struct l2_vm_value *val) { | |||
case L2_VAL_TYPE_BUFFER: | |||
{ | |||
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); | |||
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; | |||
@@ -89,4 +87,6 @@ int main() { | |||
print_var(&vm.values[i]); | |||
} | |||
} | |||
l2_vm_free(&vm); | |||
} |
@@ -42,9 +42,8 @@ static void gc_mark(struct l2_vm *vm, l2_word id) { | |||
int typ = val->flags & 0x0f; | |||
if (typ == L2_VAL_TYPE_ARRAY) { | |||
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) { | |||
gc_mark(vm, ids[i]); | |||
gc_mark(vm, arr->data[i]); | |||
} | |||
} | |||
} | |||
@@ -97,6 +96,20 @@ void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) { | |||
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) { | |||
for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) { | |||
if (vm->stackflags[sptr]) { | |||
@@ -202,15 +215,6 @@ void l2_vm_step(struct l2_vm *vm) { | |||
vm->sptr += 1; | |||
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: | |||
word = alloc_val(vm); | |||
vm->values[word].flags = L2_VAL_TYPE_BUFFER; | |||
@@ -237,6 +241,24 @@ void l2_vm_step(struct l2_vm *vm) { | |||
} | |||
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: | |||
break; | |||
} |