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:
kichikuou
2026-06-21 06:56:24 +09:00
parent 3012faa6ff
commit fab789df65
2 changed files with 31 additions and 2 deletions
+4
View File
@@ -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)
+27 -2
View File
@@ -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;
}