diff --git a/include/vm/heap.h b/include/vm/heap.h index 281a25b..cab9bd5 100644 --- a/include/vm/heap.h +++ b/include/vm/heap.h @@ -62,6 +62,7 @@ bool page_index_valid(int index); bool string_index_valid(int index); struct page *heap_get_page(int index); +struct page *heap_get_delegate_page(int index); struct string *heap_get_string(int index); void heap_set_page(int slot, struct page *page); void heap_string_assign(int slot, struct string *string); diff --git a/include/vm/page.h b/include/vm/page.h index 5f15d71..c88c5ed 100644 --- a/include/vm/page.h +++ b/include/vm/page.h @@ -29,14 +29,15 @@ enum page_type { GLOBAL_PAGE, LOCAL_PAGE, STRUCT_PAGE, - ARRAY_PAGE + ARRAY_PAGE, + DELEGATE_PAGE, }; #define NR_PAGE_TYPES (ARRAY_PAGE+1) /* * A page is an ordered collection of variables. Pages are used to implement - * global and local variables, structures and arrays as follows, + * global and local variables, structures, arrays and delegates as follows: * * Global variables: all global variables are stored in a single global page. * @@ -48,15 +49,28 @@ enum page_type { * Arrays: each array object is backed by a page storing its members. * Multi-dimensional arrays are implemented as a tree of pages (meaning the * whole array is NOT contiguous in memory). + * + * Delegates: each delegate object is backed by a page storing object/function + * pairs. */ struct page { enum page_type type; + // Value of `index`: + // ---------------- + // GLOBAL_PAGE: unused + // LOCAL_PAGE: function index + // STRUCT_PAGE: struct index + // ARRAY_PAGE: array data type (e.g. for AIN_ARRAY_STRING, AIN_STRING) + // DELEGATE_PAGE: unused union { int index; enum ain_data_type a_type; }; - int struct_type; // for array pages - int rank; // for array pages + // array-specific metadata + struct { + int struct_type; + int rank; + } array; int nr_vars; union vm_value values[]; }; @@ -115,4 +129,12 @@ void array_sort(struct page *page, int compare_fno); int array_find(struct page *page, int start, int end, union vm_value v, int compare_fno); void array_reverse(struct page *page); +// delegates +struct page *delegate_new_from_method(int obj, int fun); +int delegate_numof(struct page *page); +struct page *delegate_plusa(struct page *dst, struct page *add); +struct page *delegate_minusa(struct page *dst, struct page *minus); +struct page *delegate_clear(struct page *page); +void delegate_get(struct page *page, int i, int *obj_out, int *fun_out); + #endif /* SYSTEM4_PAGE_H */ diff --git a/src/debug-ffi.c b/src/debug-ffi.c index a7c0c97..1212d0c 100644 --- a/src/debug-ffi.c +++ b/src/debug-ffi.c @@ -162,16 +162,16 @@ sexp sexp_page_get_a_type (sexp ctx, sexp self, sexp_sint_t n, sexp x) { return sexp_make_integer(ctx, ((struct page*)sexp_cpointer_value(x))->a_type); } -sexp sexp_page_get_struct_type (sexp ctx, sexp self, sexp_sint_t n, sexp x) { +sexp sexp_page_get__page_struct_type (sexp ctx, sexp self, sexp_sint_t n, sexp x) { if (! (sexp_pointerp(x) && (sexp_pointer_tag(x) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self))))) return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), x); - return sexp_make_integer(ctx, ((struct page*)sexp_cpointer_value(x))->struct_type); + return sexp_make_integer(ctx, ((struct page*)sexp_cpointer_value(x))->_page_struct_type); } -sexp sexp_page_get_rank (sexp ctx, sexp self, sexp_sint_t n, sexp x) { +sexp sexp_page_get__page_rank (sexp ctx, sexp self, sexp_sint_t n, sexp x) { if (! (sexp_pointerp(x) && (sexp_pointer_tag(x) == sexp_unbox_fixnum(sexp_opcode_arg1_type(self))))) return sexp_type_exception(ctx, self, sexp_unbox_fixnum(sexp_opcode_arg1_type(self)), x); - return sexp_make_integer(ctx, ((struct page*)sexp_cpointer_value(x))->rank); + return sexp_make_integer(ctx, ((struct page*)sexp_cpointer_value(x))->_page_rank); } @@ -290,8 +290,8 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char tmp = sexp_string_to_symbol(ctx, name); sexp_env_define(ctx, env, tmp, sexp_page_type_obj); sexp_type_slots(sexp_page_type_obj) = SEXP_NULL; - sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "rank", -1)); - sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "struct_type", -1)); + sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "_page_rank", -1)); + sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "_page_struct_type", -1)); sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "a_type", -1)); sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "nr_vars", -1)); sexp_push(ctx, sexp_type_slots(sexp_page_type_obj), sexp_intern(ctx, "index", -1)); @@ -301,13 +301,13 @@ sexp sexp_init_library (sexp ctx, sexp self, sexp_sint_t n, sexp env, const char tmp = sexp_make_type_predicate(ctx, name, sexp_page_type_obj); name = sexp_intern(ctx, "page?", 5); sexp_env_define(ctx, env, name, tmp); - op = sexp_define_foreign(ctx, env, "array-rank", 1, sexp_page_get_rank); + op = sexp_define_foreign(ctx, env, "array-rank", 1, sexp_page_get__page_rank); if (sexp_opcodep(op)) { sexp_opcode_return_type(op) = sexp_make_fixnum(SEXP_FIXNUM); sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_type_tag(sexp_page_type_obj)); } if (sexp_vectorp(sexp_type_getters(sexp_page_type_obj))) sexp_vector_set(sexp_type_getters(sexp_page_type_obj), SEXP_FIVE, op); - op = sexp_define_foreign(ctx, env, "array-struct-type", 1, sexp_page_get_struct_type); + op = sexp_define_foreign(ctx, env, "array-struct-type", 1, sexp_page_get__page_struct_type); if (sexp_opcodep(op)) { sexp_opcode_return_type(op) = sexp_make_fixnum(SEXP_FIXNUM); sexp_opcode_arg1_type(op) = sexp_make_fixnum(sexp_type_tag(sexp_page_type_obj)); diff --git a/src/debug-ffi.stub b/src/debug-ffi.stub index e43df63..beb1fbf 100644 --- a/src/debug-ffi.stub +++ b/src/debug-ffi.stub @@ -63,8 +63,8 @@ (int nr_vars page-nr-vars) (int a_type array-data-type) - (int struct_type array-struct-type) - (int rank array-rank)) + (int _page_struct_type array-struct-type) + (int _page_rank array-rank)) (define-c-union vm_value predicate: vm-value? diff --git a/src/debugger.c b/src/debugger.c index 3928037..6c9031a 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -111,6 +111,8 @@ static const char *variable_name(struct page *page, int varno) return ain->structures[page->index].members[varno].name; case ARRAY_PAGE: return "array member"; + case DELEGATE_PAGE: + return "delegate member"; } return "unknown"; } @@ -217,6 +219,10 @@ static struct page *frame_page(int i) return get_page(call_stack[call_stack_ptr - (i+1)].page_slot); } +// XXX: chibi-ffi doesn't support anonymous structs +#define _page_struct_type array.struct_type +#define _page_rank array.rank + // autogenerated with `chibi-ffi src/debug-ffi.stub` #include "debug-ffi.c" diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c index 50f81bf..2a3892f 100644 --- a/src/dungeon/dungeon.c +++ b/src/dungeon/dungeon.c @@ -356,7 +356,7 @@ static int find_walk_data(struct page *array, int map_no, struct dgn *dgn) { if (!array) return WALK_DATA_BROKEN; - if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->rank != 1) + if (array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1) VM_ERROR("Not a flat integer array"); int ptr = 0; diff --git a/src/heap.c b/src/heap.c index 47e2050..5050544 100644 --- a/src/heap.c +++ b/src/heap.c @@ -222,6 +222,14 @@ struct string *heap_get_string(int index) return heap[index].s; } +struct page *heap_get_delegate_page(int index) +{ + struct page *page = heap_get_page(index); + if (!page || page->type != DELEGATE_PAGE) + VM_ERROR("Not a delegate page: %d", index); + return page; +} + void heap_set_page(int slot, struct page *page) { #ifdef DEBUG_HEAP diff --git a/src/hll/Bitarray.c b/src/hll/Bitarray.c index 6baef18..32fab8a 100644 --- a/src/hll/Bitarray.c +++ b/src/hll/Bitarray.c @@ -99,7 +99,7 @@ static void Bitarray_GetArray(int bitSet, struct page **page) return; struct page *array = *page; - if (!array || array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->rank != 1) + if (!array || array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1) ERROR("Not an flat integer array"); int n = (arrays[bitSet].size + 31) / 32; @@ -117,7 +117,7 @@ static void Bitarray_SetArray(int bitSet, struct page **page) return; struct page *array = *page; - if (!array || array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->rank != 1) + if (!array || array->type != ARRAY_PAGE || array->a_type != AIN_ARRAY_INT || array->array.rank != 1) ERROR("Not an flat integer array"); int n = (arrays[bitSet].size + 31) / 32; diff --git a/src/hll/iarray.c b/src/hll/iarray.c index ac0221d..178e3e7 100644 --- a/src/hll/iarray.c +++ b/src/hll/iarray.c @@ -122,9 +122,9 @@ void iarray_write_array(struct iarray_writer *w, struct page *page) assert(page->type == ARRAY_PAGE); struct ain_type t = { - .data = page->rank > 1 ? page->a_type : array_type(page->a_type), - .struc = page->struct_type, - .rank = page->rank - 1 + .data = page->array.rank > 1 ? page->a_type : array_type(page->a_type), + .struc = page->array.struct_type, + .rank = page->array.rank - 1 }; iarray_write(w, page->nr_vars); @@ -230,8 +230,8 @@ struct page *iarray_read_array(struct iarray_reader *r, struct ain_type *t) int nr_vars = iarray_read(r); struct page *page = alloc_page(ARRAY_PAGE, t->data, nr_vars); - page->struct_type = t->struc; - page->rank = t->rank; + page->array.struct_type = t->struc; + page->array.rank = t->rank; for (int i = 0; i < nr_vars; i++) { page->values[i].i = iarray_read_member(r, &next_t); diff --git a/src/page.c b/src/page.c index a837038..1a375f6 100644 --- a/src/page.c +++ b/src/page.c @@ -29,7 +29,8 @@ static const char *pagetype_strtab[] = { [GLOBAL_PAGE] = "GLOBAL_PAGE", [LOCAL_PAGE] = "LOCAL_PAGE", [STRUCT_PAGE] = "STRUCT_PAGE", - [ARRAY_PAGE] = "ARRAY_PAGE" + [ARRAY_PAGE] = "ARRAY_PAGE", + [DELEGATE_PAGE] = "DELEGATE_PAGE", }; const char *pagetype_string(enum page_type type) @@ -168,10 +169,19 @@ enum ain_data_type variable_type(struct page *page, int varno, int *struct_type, return ain->structures[page->index].members[varno].type.data; case ARRAY_PAGE: if (struct_type) - *struct_type = page->struct_type; + *struct_type = page->array.struct_type; if (array_rank) - *array_rank = page->rank - 1; - return page->rank > 1 ? page->a_type : array_type(page->a_type); + *array_rank = page->array.rank - 1; + return page->array.rank > 1 ? page->a_type : array_type(page->a_type); + case DELEGATE_PAGE: + if (varno % 2 == 0) { + if (struct_type && page->values[varno].i >= 0) + *struct_type = heap_get_page(page->values[varno].i)->index; + if (array_rank) + *array_rank = -1; + return AIN_STRUCT; + } + return AIN_VOID; } return AIN_VOID; } @@ -207,8 +217,7 @@ struct page *copy_page(struct page *src) if (!src) return NULL; struct page *dst = alloc_page(src->type, src->index, src->nr_vars); - dst->struct_type = src->struct_type; - dst->rank = src->rank; + dst->array = src->array; for (int i = 0; i < src->nr_vars; i++) { dst->values[i] = vm_copy(src->values[i], variable_type(src, i, NULL, NULL)); @@ -282,8 +291,8 @@ struct page *alloc_array(int rank, union vm_value *dimensions, enum ain_data_typ data_type = unref_array_type(data_type); enum ain_data_type type = array_type(data_type); struct page *page = alloc_page(ARRAY_PAGE, data_type, dimensions->i); - page->struct_type = struct_type; - page->rank = rank; + page->array.struct_type = struct_type; + page->array.rank = rank; for (int i = 0; i < dimensions->i; i++) { if (rank == 1) { @@ -311,7 +320,7 @@ struct page *realloc_array(struct page *src, int rank, union vm_value *dimension return alloc_array(rank, dimensions, data_type, struct_type, init_structs); if (src->type != ARRAY_PAGE) VM_ERROR("Not an array"); - if (src->rank != rank) + if (src->array.rank != rank) VM_ERROR("Attempt to reallocate array with different rank"); if (!dimensions->i) { delete_page_vars(src); @@ -354,7 +363,7 @@ int array_numof(struct page *page, int rank) { if (!page) return 0; - if (rank < 1 || rank > page->rank) + if (rank < 1 || rank > page->array.rank) return 0; if (rank == 1) { return page->nr_vars; @@ -379,7 +388,7 @@ void array_copy(struct page *dst, int dst_i, struct page *src, int src_i, int n) VM_ERROR("Out of bounds array access"); if (!array_index_ok(dst, dst_i + n - 1) || !array_index_ok(src, src_i + n - 1)) VM_ERROR("Out of bounds array access"); - if (dst->rank != 1 || src->rank != 1) + if (dst->array.rank != 1 || src->array.rank != 1) VM_ERROR("Tried to copy to/from a multi-dimensional array"); if (dst->a_type != src->a_type) VM_ERROR("Array types do not match"); @@ -420,12 +429,12 @@ struct page *array_pushback(struct page *dst, union vm_value v, enum ain_data_ty if (dst) { if (dst->type != ARRAY_PAGE) VM_ERROR("Not an array"); - if (dst->rank != 1) + if (dst->array.rank != 1) VM_ERROR("Tried pushing to a multi-dimensional array"); int index = dst->nr_vars; union vm_value dims[1] = { (union vm_value) { .i = index + 1 } }; - dst = realloc_array(dst, 1, dims, dst->a_type, dst->struct_type, false); + dst = realloc_array(dst, 1, dims, dst->a_type, dst->array.struct_type, false); variable_set(dst, index, array_type(data_type), v); } else { union vm_value dims[1] = { (union vm_value) { .i = 1 } }; @@ -441,11 +450,11 @@ struct page *array_popback(struct page *dst) return NULL; if (dst->type != ARRAY_PAGE) VM_ERROR("Not an array"); - if (dst->rank != 1) + if (dst->array.rank != 1) VM_ERROR("Tried popping from a multi-dimensional array"); union vm_value dims[1] = { (union vm_value) { .i = dst->nr_vars - 1 } }; - dst = realloc_array(dst, 1, dims, dst->a_type, dst->struct_type, false); + dst = realloc_array(dst, 1, dims, dst->a_type, dst->array.struct_type, false); return dst; } @@ -456,7 +465,7 @@ struct page *array_erase(struct page *page, int i, bool *success) return NULL; if (page->type != ARRAY_PAGE) VM_ERROR("Not an array"); - if (page->rank != 1) + if (page->array.rank != 1) VM_ERROR("Tried erasing from a multi-dimensional array"); if (!array_index_ok(page, i)) return page; @@ -488,7 +497,7 @@ struct page *array_insert(struct page *page, int i, union vm_value v, enum ain_d } if (page->type != ARRAY_PAGE) VM_ERROR("Not an array"); - if (page->rank != 1) + if (page->array.rank != 1) VM_ERROR("Tried inserting into a multi-dimensional array"); // NOTE: you cannot insert at the end of an array due to how i is clamped @@ -576,3 +585,100 @@ void array_reverse(struct page *page) page->values[end] = tmp; } } + +struct page *delegate_new_from_method(int obj, int fun) +{ + struct page *page = alloc_page(DELEGATE_PAGE, 0, 2); + page->values[0].i = obj; + page->values[1].i = fun; + if (obj >= 0) { + heap_ref(obj); + } + return page; +} + +int delegate_numof(struct page *page) +{ + if (page->type != DELEGATE_PAGE) + VM_ERROR("Not a delegate"); + return page->nr_vars / 2; +} + +struct page *delegate_plusa(struct page *dst, struct page *add) +{ + if (dst->type != DELEGATE_PAGE || add->type != DELEGATE_PAGE) + VM_ERROR("Not a delegate"); + + // FIXME: duplicate checking needed? + int new_vars = dst->nr_vars + add->nr_vars; + dst = xrealloc(dst, sizeof(struct page) + sizeof(union vm_value) * new_vars); + for (int i = 0; i < add->nr_vars; i += 2) { + if (add->values[i].i >= 0) { + heap_ref(add->values[i].i); + } + dst->values[dst->nr_vars+i+0].i = add->values[i+0].i; + dst->values[dst->nr_vars+i+1].i = add->values[i+1].i; + } + dst->nr_vars = new_vars; + return dst; +} + +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; + } + } + } + + // 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; +} + +struct page *delegate_clear(struct page *page) +{ + 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 >= 0) + heap_unref(page->values[i].i); + page->values[i].i = -1; + page->values[i+1].i = -1; + } + page->index = 0; + page->nr_vars = 0; + return page; +} + +void delegate_get(struct page *page, int i, int *obj_out, int *fun_out) +{ + if (page->type != DELEGATE_PAGE) + VM_ERROR("Not a delegate"); + if (i*2 >= page->nr_vars) + VM_ERROR("Invalid delegate index: %d", i); + *obj_out = page->values[i*2].i; + *fun_out = page->values[i*2+1].i; +} diff --git a/src/resume.c b/src/resume.c index c9b1f15..93fe24d 100644 --- a/src/resume.c +++ b/src/resume.c @@ -66,8 +66,8 @@ static cJSON *resume_page_to_json(struct page *page) cJSON_AddStringToObject(json, "type", page_type_strtab[page->type]); cJSON_AddNumberToObject(json, "subtype", page->index); if (page->type == ARRAY_PAGE) { - cJSON_AddNumberToObject(json, "struct-type", page->struct_type); - cJSON_AddNumberToObject(json, "rank", page->rank); + cJSON_AddNumberToObject(json, "struct-type", page->array.struct_type); + cJSON_AddNumberToObject(json, "rank", page->array.rank); } cJSON *values = cJSON_CreateArray(); @@ -200,8 +200,8 @@ static void load_page(int slot, cJSON *json) // allocate page struct page *page = alloc_page(page_type, subtype->valueint, cJSON_GetArraySize(values)); - page->struct_type = struct_type; - page->rank = rank; + page->array.struct_type = struct_type; + page->array.rank = rank; // init page variables int i = 0; diff --git a/src/vm.c b/src/vm.c index f495e37..6d7b622 100644 --- a/src/vm.c +++ b/src/vm.c @@ -78,6 +78,12 @@ int32_t call_stack_ptr = 0; struct ain *ain; size_t instr_ptr = 0; +static struct { + struct page *page; + int index; + int nr_functions; +} current_delegate; + // Read the opcode at ADDR. static int16_t get_opcode(size_t addr) { @@ -2007,6 +2013,106 @@ static enum opcode execute_instruction(enum opcode opcode) stack_push(i < get_argument(1) || i >= get_argument(2)); break; } + //case DG_ADD: + //case DG_SET: + case DG_CALL: { // DG_TYPE, ADDR + int dg = get_argument(0); + if (dg < 0 || dg >= ain->nr_delegates) + VM_ERROR("Invalid delegate index"); + int obj, fun; + delegate_get(current_delegate.page, current_delegate.index, &obj, &fun); + // pop previous return value + if (ain->delegates[dg].return_type.data != AIN_VOID) { + stack_pop(); + } + // call function + vm_call(fun, obj); + if (++current_delegate.index >= current_delegate.nr_functions) { + // clear delegate state + current_delegate.page = NULL; + current_delegate.index = 0; + current_delegate.nr_functions = 0; + // jump to addr + instr_ptr = get_argument(1); + } else { + // continue to next instruction + instr_ptr += 10; + } + break; + } + case DG_NUMOF: { + stack_push(delegate_numof(heap_get_page(stack_pop().i))); + break; + } + //case DG_EXIST: + //case DG_ERASE: + case DG_CLEAR: { + int slot = stack_pop().i; + if (!slot) + break; + heap_set_page(slot, delegate_clear(heap_get_delegate_page(slot))); + break; + } + case DG_COPY: { + stack_push(vm_copy_page(heap_get_delegate_page(stack_pop().i))); + break; + } + case DG_ASSIGN: { + int set_i = stack_pop().i; + int dst_i = stack_pop().i; + struct page *set = heap_get_delegate_page(set_i); + delete_page(dst_i); + heap_set_page(dst_i, copy_page(set)); + stack_push(set_i); + break; + } + case DG_PLUSA: { + int add_i = stack_pop().i; + int dst_i = stack_pop().i; + struct page *add = heap_get_delegate_page(add_i); + struct page *dst = heap_get_delegate_page(dst_i); + heap_set_page(dst_i, delegate_plusa(dst, add)); + stack_push(add_i); + break; + } + case DG_MINUSA: { + int minus_i = stack_pop().i; + int dst_i = stack_pop().i; + struct page *minus = heap_get_delegate_page(minus_i); + struct page *dst = heap_get_delegate_page(dst_i); + heap_set_page(dst_i, delegate_minusa(dst, minus)); + stack_push(minus_i); + break; + } + case DG_POP: { + heap_unref(stack_pop().i); + break; + } + case DG_NEW_FROM_METHOD: { + int fun = stack_pop().i; + int obj = stack_pop().i; + stack_push(heap_alloc_page(delegate_new_from_method(obj, fun))); + break; + } + case DG_CALLBEGIN: { // DG_TYPE + int dg = get_argument(0); + if (dg < 0 || dg >= ain->nr_delegates) + VM_ERROR("Invalid delegate index"); + struct page *page = heap_get_page(stack_pop().i); + if (page->type != DELEGATE_PAGE) + VM_ERROR("Not a delegate"); + current_delegate.page = page; + current_delegate.index = 0; + current_delegate.nr_functions = delegate_numof(page); + // XXX: If the delegate has a return value, we push a dummy value + // so that DG_CALL can replace it + if (ain->delegates[dg].return_type.data != AIN_VOID) { + stack_push(0); + } + break; + } + //case DG_NEW: + //case DG_STR_TO_METHOD: // -- NOOPs --- case FUNC: break; @@ -2168,10 +2274,14 @@ static void describe_page(struct page *page) free(u); break; case ARRAY_PAGE: - u = sjis2utf(ain_strtype(ain, page->a_type, page->struct_type), 0); + u = sjis2utf(ain_strtype(ain, page->a_type, page->array.struct_type), 0); sys_message("ARRAY_PAGE: %s\n", u); free(u); break; + case DELEGATE_PAGE: + // TODO: list function names + sys_message("DELEGATE_PAGE\n"); + break; } } diff --git a/subprojects/libsys4 b/subprojects/libsys4 index a397645..cbdf4ae 160000 --- a/subprojects/libsys4 +++ b/subprojects/libsys4 @@ -1 +1 @@ -Subproject commit a3976458d45940f0d72c1b7b67824e0531320baa +Subproject commit cbdf4ae8abaeb7aa79b068cfbaf6813d2d82c606