From 3e536af09a5a759e7ae79a0098b6913fcb19aaee Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Tue, 2 Aug 2022 18:16:16 -0700 Subject: [PATCH] Implement DG_ADD, DG_EXIST, DG_ERASE --- include/vm/page.h | 2 ++ src/page.c | 49 +++++++++++++++++++++++------------------------ src/vm.c | 25 +++++++++++++++++++++--- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/include/vm/page.h b/include/vm/page.h index 5ed4a48..bde2487 100644 --- a/include/vm/page.h +++ b/include/vm/page.h @@ -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); diff --git a/src/page.c b/src/page.c index 8c01bbf..fa720b3 100644 --- a/src/page.c +++ b/src/page.c @@ -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; } diff --git a/src/vm.c b/src/vm.c index f72aee9..9f21eb7 100644 --- a/src/vm.c +++ b/src/vm.c @@ -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)