Implement DG_ADD, DG_EXIST, DG_ERASE

This commit is contained in:
Nunuhara Cabbage
2022-08-02 18:16:16 -07:00
parent 62a2dc003c
commit 3e536af09a
3 changed files with 48 additions and 28 deletions
+2
View File
@@ -133,6 +133,8 @@ void array_reverse(struct page *page);
// delegates
struct page *delegate_new_from_method(int obj, int fun);
int delegate_numof(struct page *page);
bool delegate_contains(struct page *dst, int obj, int fun);
void delegate_erase(struct page *page, int obj, int fun);
struct page *delegate_append(struct page *dst, int obj, int fun);
struct page *delegate_plusa(struct page *dst, struct page *add);
struct page *delegate_minusa(struct page *dst, struct page *minus);
+24 -25
View File
@@ -624,8 +624,10 @@ struct page *delegate_new_from_method(int obj, int fun)
return page;
}
static bool delegate_contains(struct page *dst, int obj, int fun)
bool delegate_contains(struct page *dst, int obj, int fun)
{
if (!dst)
return false;
for (int i = 0; i < dst->nr_vars; i += 2) {
if (dst->values[i].i == obj && dst->values[i+1].i == fun)
return true;
@@ -660,6 +662,26 @@ int delegate_numof(struct page *page)
return page->nr_vars / 2;
}
void delegate_erase(struct page *page, int obj, int fun)
{
if (!page)
return;
if (page->type != DELEGATE_PAGE)
VM_ERROR("Not a delegate");
for (int i = 0; i < page->nr_vars; i+= 2) {
if (page->values[i].i == obj && page->values[i+1].i == fun) {
if (page->values[i].i >= 0)
heap_unref(page->values[i].i);
for (int j = i+2; j < page->nr_vars; j += 2) {
page->values[j-2].i = page->values[j+0].i;
page->values[j-1].i = page->values[j+1].i;
}
page->nr_vars -= 2;
break;
}
}
}
struct page *delegate_plusa(struct page *dst, struct page *add)
{
if (!add)
@@ -682,33 +704,10 @@ struct page *delegate_minusa(struct page *dst, struct page *minus)
if (dst->type != DELEGATE_PAGE || minus->type != DELEGATE_PAGE)
VM_ERROR("Not a delegate");
// set matching obj/fun pairs to -1/-1
int removed = 0;
for (int i = 0; i < minus->nr_vars; i += 2) {
for (int j = 0; j < dst->nr_vars; j += 2) {
if (minus->values[i].i == dst->values[j].i && minus->values[i+1].i == dst->values[j+1].i) {
if (dst->values[j].i >= 0)
heap_unref(dst->values[j].i);
dst->values[j].i = -1;
dst->values[j+1].i = -1;
removed++;
break;
}
}
delegate_erase(dst, minus->values[i].i, minus->values[i+1].i);
}
// shift values to fill in gaps
for (int i = 0, p = 0; i < dst->nr_vars; i += 2) {
if (dst->values[i].i == -1 && dst->values[i+1].i == -1)
continue;
if (p < i) {
dst->values[p+0].i = dst->values[i+0].i;
dst->values[p+1].i = dst->values[i+1].i;
}
p += 2;
}
dst->nr_vars -= removed;
return dst;
}
+22 -3
View File
@@ -2080,7 +2080,14 @@ static enum opcode execute_instruction(enum opcode opcode)
array_sort_mem(heap[array].page, mno);
break;
}
//case DG_ADD:
case DG_ADD: {
int fun = stack_pop().i;
int obj = stack_pop().i;
int dg_i = stack_pop().i;
delete_page(dg_i);
heap_set_page(dg_i, delegate_new_from_method(obj, fun));
break;
}
case DG_SET: {
int fun = stack_pop().i;
int obj = stack_pop().i;
@@ -2135,8 +2142,20 @@ static enum opcode execute_instruction(enum opcode opcode)
stack_push(delegate_numof(heap_get_delegate_page(dg)));
break;
}
//case DG_EXIST:
//case DG_ERASE:
case DG_EXIST: {
int fun = stack_pop().i;
int obj = stack_pop().i;
int dg_i = stack_pop().i;
stack_push(delegate_contains(heap_get_delegate_page(dg_i), obj, fun));
break;
}
case DG_ERASE: {
int fun = stack_pop().i;
int obj = stack_pop().i;
int dg_i = stack_pop().i;
delegate_erase(heap_get_delegate_page(dg_i), obj, fun);
break;
}
case DG_CLEAR: {
int slot = stack_pop().i;
if (!slot)