mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-08 22:59:57 +03:00
Implement DG_ADD, DG_EXIST, DG_ERASE
This commit is contained in:
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user