mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
VM: Check function signature in DG_STR_TO_METHOD
Only resolve the method when the function's signature matches the delegate type, returning 0 otherwise. Also, DG_SET / DG_NEW_FROM_METHOD / DG_ADD should not add function 0.
This commit is contained in:
@@ -703,6 +703,8 @@ void array_reverse(struct page *page)
|
||||
|
||||
struct page *delegate_new_from_method(int obj, int fun)
|
||||
{
|
||||
if (fun < 1)
|
||||
return alloc_page(DELEGATE_PAGE, 0, 0);
|
||||
struct page *page = alloc_page(DELEGATE_PAGE, 0, 3);
|
||||
page->values[0].i = obj;
|
||||
page->values[1].i = fun;
|
||||
@@ -725,6 +727,8 @@ bool delegate_contains(struct page *dst, int obj, int fun)
|
||||
|
||||
struct page *delegate_append(struct page *dst, int obj, int fun)
|
||||
{
|
||||
if (fun < 1)
|
||||
return dst;
|
||||
if (!dst)
|
||||
return delegate_new_from_method(obj, fun);
|
||||
if (dst->type != DELEGATE_PAGE)
|
||||
|
||||
@@ -267,6 +267,30 @@ static int get_function_by_name(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check whether a function's signature is compatible with a delegate type.
|
||||
static bool function_matches_delegate(int dg_no, int fno)
|
||||
{
|
||||
if (dg_no < 0 || dg_no >= ain->nr_delegates)
|
||||
return false;
|
||||
if (fno < 0 || fno >= ain->nr_functions)
|
||||
return false;
|
||||
struct ain_function_type *dg = &ain->delegates[dg_no];
|
||||
struct ain_function *f = &ain->functions[fno];
|
||||
|
||||
if (dg->return_type.data != f->return_type.data ||
|
||||
dg->return_type.struc != f->return_type.struc)
|
||||
return false;
|
||||
if (dg->nr_arguments != f->nr_args)
|
||||
return false;
|
||||
for (int i = 0; i < dg->nr_arguments; i++) {
|
||||
struct ain_type *a = &dg->variables[i].type;
|
||||
struct ain_type *b = &f->vars[i].type;
|
||||
if (a->data != b->data || a->struc != b->struc || a->rank != b->rank)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int scenario_label_addr(const char *lname)
|
||||
{
|
||||
for (int i = 0; i < ain->nr_scenario_labels; i++) {
|
||||
@@ -2326,9 +2350,10 @@ static enum opcode execute_instruction(enum opcode opcode)
|
||||
break;
|
||||
}
|
||||
case DG_STR_TO_METHOD: {
|
||||
stack_pop(); // delegate type index
|
||||
int dg_no = stack_pop().i;
|
||||
int str = stack_pop().i;
|
||||
stack_push(get_function_by_name(heap_get_string(str)->text));
|
||||
int fno = get_function_by_name(heap_get_string(str)->text);
|
||||
stack_push(function_matches_delegate(dg_no, fno) ? fno : 0);
|
||||
heap_unref(str);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user